@remotion/media-parser 4.0.237 → 4.0.239

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 (106) 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/parse-ebml.js +1 -1
  58. package/dist/buffer-iterator.d.ts +2 -0
  59. package/dist/buffer-iterator.js +25 -0
  60. package/dist/convert-audio-or-video-sample.d.ts +2 -0
  61. package/dist/convert-audio-or-video-sample.js +17 -0
  62. package/dist/create/iso-base-media/create-iso-base-media.js +38 -19
  63. package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.js +7 -1
  64. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.js +3 -0
  65. package/dist/create/media-fn.d.ts +0 -1
  66. package/dist/create/progress-tracker.d.ts +2 -0
  67. package/dist/create/progress-tracker.js +32 -8
  68. package/dist/emit-available-info.js +1 -1
  69. package/dist/esm/index.mjs +1288 -252
  70. package/dist/get-container.d.ts +1 -1
  71. package/dist/get-container.js +3 -0
  72. package/dist/get-duration.js +4 -1
  73. package/dist/get-fps.js +8 -2
  74. package/dist/get-tracks.d.ts +4 -3
  75. package/dist/get-tracks.js +9 -2
  76. package/dist/get-video-codec.d.ts +1 -2
  77. package/dist/get-video-codec.js +9 -148
  78. package/dist/index.d.ts +2 -0
  79. package/dist/metadata/get-metadata.js +3 -0
  80. package/dist/options.d.ts +3 -3
  81. package/dist/parse-media.js +3 -3
  82. package/dist/parse-result.d.ts +7 -2
  83. package/dist/parse-video.js +15 -0
  84. package/dist/register-track.d.ts +5 -5
  85. package/dist/register-track.js +16 -10
  86. package/dist/state/has-tracks-section.d.ts +3 -0
  87. package/dist/state/has-tracks-section.js +5 -0
  88. package/dist/state/parser-state.d.ts +2 -0
  89. package/dist/version.d.ts +1 -1
  90. package/dist/version.js +1 -1
  91. package/dist/webcodec-sample-types.d.ts +9 -2
  92. package/package.json +3 -3
  93. package/dist/add-new-matroska-tracks.d.ts +0 -13
  94. package/dist/add-new-matroska-tracks.js +0 -29
  95. package/dist/boxes/iso-base-media/meta/keys.d.ts +0 -10
  96. package/dist/boxes/iso-base-media/meta/keys.js +0 -17
  97. package/dist/boxes/iso-base-media/meta/list.d.ts +0 -12
  98. package/dist/boxes/iso-base-media/meta/list.js +0 -33
  99. package/dist/boxes/riff/strf.d.ts +0 -7
  100. package/dist/boxes/riff/strf.js +0 -67
  101. package/dist/create/mp3/create-mp3.d.ts +0 -2
  102. package/dist/create/mp3/create-mp3.js +0 -49
  103. package/dist/get-metadata.d.ts +0 -7
  104. package/dist/get-metadata.js +0 -63
  105. package/dist/parser-state.d.ts +0 -33
  106. 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.239";
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);
@@ -6124,7 +6238,7 @@ var emitAvailableInfo = ({
6124
6238
  }
6125
6239
  if (key === "videoCodec") {
6126
6240
  if (returnValue.videoCodec === undefined && hasInfo.videoCodec && parseResult) {
6127
- const videoCodec = getVideoCodec(parseResult.segments);
6241
+ const videoCodec = getVideoCodec(parseResult.segments, state);
6128
6242
  moreFields.onVideoCodec?.(videoCodec);
6129
6243
  returnValue.videoCodec = videoCodec;
6130
6244
  }
@@ -6260,29 +6374,35 @@ var hasAllInfo = ({
6260
6374
 
6261
6375
  // src/register-track.ts
6262
6376
  var registerTrack = async ({
6263
- state,
6264
6377
  options,
6265
- track
6378
+ track,
6379
+ container
6266
6380
  }) => {
6267
- if (track.type === "video" && options.onVideoTrack) {
6268
- const callback = await options.onVideoTrack(track);
6269
- await state.registerVideoSampleCallback(track.trackId, callback ?? null);
6381
+ if (track.type === "video") {
6382
+ options.parserState.tracks.addTrack(track);
6383
+ if (options.onVideoTrack) {
6384
+ const callback = await options.onVideoTrack({ track, container });
6385
+ await options.parserState.registerVideoSampleCallback(track.trackId, callback ?? null);
6386
+ }
6270
6387
  }
6271
- if (track.type === "audio" && options.onAudioTrack) {
6272
- const callback = await options.onAudioTrack(track);
6273
- await state.registerAudioSampleCallback(track.trackId, callback ?? null);
6388
+ if (track.type === "audio") {
6389
+ options.parserState.tracks.addTrack(track);
6390
+ if (options.onAudioTrack) {
6391
+ const callback = await options.onAudioTrack({ track, container });
6392
+ await options.parserState.registerAudioSampleCallback(track.trackId, callback ?? null);
6393
+ }
6274
6394
  }
6275
6395
  };
6276
6396
  var registerVideoTrackWhenProfileIsAvailable = ({
6277
6397
  options,
6278
- state,
6279
- track
6398
+ track,
6399
+ container
6280
6400
  }) => {
6281
- state.registerOnAvcProfileCallback(async (profile) => {
6401
+ options.parserState.registerOnAvcProfileCallback(async (profile) => {
6282
6402
  await registerTrack({
6283
6403
  options,
6284
- state,
6285
- track: addAvcProfileToTrack(track, profile)
6404
+ track: addAvcProfileToTrack(track, profile),
6405
+ container
6286
6406
  });
6287
6407
  });
6288
6408
  };
@@ -6445,6 +6565,20 @@ var parseFtyp = ({
6445
6565
  };
6446
6566
  };
6447
6567
 
6568
+ // src/convert-audio-or-video-sample.ts
6569
+ var convertAudioOrVideoSampleToWebCodecsTimestamps = (sample, timescale2) => {
6570
+ const { cts, dts, timestamp } = sample;
6571
+ return {
6572
+ cts: cts * 1e6 / timescale2,
6573
+ dts: dts * 1e6 / timescale2,
6574
+ timestamp: timestamp * 1e6 / timescale2,
6575
+ duration: (sample.duration ?? 0) * 1e6 / timescale2,
6576
+ data: sample.data,
6577
+ trackId: sample.trackId,
6578
+ type: sample.type
6579
+ };
6580
+ };
6581
+
6448
6582
  // src/boxes/iso-base-media/mdat/mdat.ts
6449
6583
  var parseMdat = async ({
6450
6584
  data,
@@ -6518,31 +6652,28 @@ var parseMdat = async ({
6518
6652
  break;
6519
6653
  }
6520
6654
  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;
6655
+ const { cts, dts, duration: duration2 } = samplesWithIndex.samplePosition;
6525
6656
  if (samplesWithIndex.track.type === "audio") {
6526
- await options.parserState.onAudioSample(samplesWithIndex.track.trackId, {
6657
+ await options.parserState.onAudioSample(samplesWithIndex.track.trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
6527
6658
  data: bytes,
6528
- timestamp,
6659
+ timestamp: cts,
6529
6660
  duration: duration2,
6530
6661
  cts,
6531
6662
  dts,
6532
6663
  trackId: samplesWithIndex.track.trackId,
6533
6664
  type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
6534
- });
6665
+ }, samplesWithIndex.track.timescale));
6535
6666
  }
6536
6667
  if (samplesWithIndex.track.type === "video") {
6537
- await options.parserState.onVideoSample(samplesWithIndex.track.trackId, {
6668
+ await options.parserState.onVideoSample(samplesWithIndex.track.trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
6538
6669
  data: bytes,
6539
- timestamp,
6670
+ timestamp: cts,
6540
6671
  duration: duration2,
6541
6672
  cts,
6542
6673
  dts,
6543
6674
  trackId: samplesWithIndex.track.trackId,
6544
6675
  type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
6545
- });
6676
+ }, samplesWithIndex.track.timescale));
6546
6677
  }
6547
6678
  const remaining = size - (data.counter.getOffset() - fileOffset);
6548
6679
  data.removeBytesRead();
@@ -8230,8 +8361,8 @@ var processBox = async ({
8230
8361
  if (transformedTrack) {
8231
8362
  await registerTrack({
8232
8363
  options,
8233
- state: options.parserState,
8234
- track: transformedTrack
8364
+ track: transformedTrack,
8365
+ container: "mp4"
8235
8366
  });
8236
8367
  }
8237
8368
  return {
@@ -8554,15 +8685,164 @@ var isMoviAtom = (iterator, ckId) => {
8554
8685
  return listType === "movi";
8555
8686
  };
8556
8687
 
8688
+ // src/boxes/avc/key.ts
8689
+ var getKeyFrameOrDeltaFromAvcInfo = (infos) => {
8690
+ const keyOrDelta = infos.find((i) => i.type === "keyframe" || i.type === "delta-frame");
8691
+ if (!keyOrDelta) {
8692
+ throw new Error("expected avc to contain info about key or delta");
8693
+ }
8694
+ return keyOrDelta.type === "keyframe" ? "key" : "delta";
8695
+ };
8696
+
8557
8697
  // src/boxes/avc/parse-avc.ts
8698
+ var Extended_SAR = 255;
8699
+ var readVuiParameters = (iterator) => {
8700
+ let sar_width = null;
8701
+ let sar_height = null;
8702
+ let overscan_appropriate_flag = null;
8703
+ let video_format = null;
8704
+ let video_full_range_flag = null;
8705
+ let colour_primaries = null;
8706
+ let transfer_characteristics = null;
8707
+ let matrix_coefficients = null;
8708
+ let chroma_sample_loc_type_top_field = null;
8709
+ let chroma_sample_loc_type_bottom_field = null;
8710
+ const aspect_ratio_info_present_flag = iterator.getBits(1);
8711
+ if (aspect_ratio_info_present_flag) {
8712
+ const aspect_ratio_idc = iterator.getBits(8);
8713
+ if (aspect_ratio_idc === Extended_SAR) {
8714
+ sar_width = iterator.getBits(16);
8715
+ sar_height = iterator.getBits(16);
8716
+ }
8717
+ }
8718
+ const overscan_info_present_flag = iterator.getBits(1);
8719
+ if (overscan_info_present_flag) {
8720
+ overscan_appropriate_flag = iterator.getBits(1);
8721
+ }
8722
+ const video_signal_type_present_flag = iterator.getBits(1);
8723
+ if (video_signal_type_present_flag) {
8724
+ video_format = iterator.getBits(3);
8725
+ video_full_range_flag = Boolean(iterator.getBits(1));
8726
+ const colour_description_present_flag = iterator.getBits(1);
8727
+ if (colour_description_present_flag) {
8728
+ colour_primaries = iterator.getBits(8);
8729
+ transfer_characteristics = iterator.getBits(8);
8730
+ matrix_coefficients = iterator.getBits(8);
8731
+ }
8732
+ }
8733
+ const chroma_loc_info_present_flag = iterator.getBits(1);
8734
+ if (chroma_loc_info_present_flag) {
8735
+ chroma_sample_loc_type_top_field = iterator.readExpGolomb();
8736
+ chroma_sample_loc_type_bottom_field = iterator.readExpGolomb();
8737
+ }
8738
+ return {
8739
+ sar_width,
8740
+ sar_height,
8741
+ overscan_appropriate_flag,
8742
+ chroma_sample_loc_type_bottom_field,
8743
+ chroma_sample_loc_type_top_field,
8744
+ colour_primaries,
8745
+ matrix_coefficients,
8746
+ transfer_characteristics,
8747
+ video_format,
8748
+ video_full_range_flag
8749
+ };
8750
+ };
8558
8751
  var readSps = (iterator) => {
8559
8752
  const profile = iterator.getUint8();
8560
8753
  const compatibility = iterator.getUint8();
8561
8754
  const level = iterator.getUint8();
8755
+ iterator.startReadingBits();
8756
+ const seq_parameter_set_id = iterator.readExpGolomb();
8757
+ let separate_colour_plane_flag = null;
8758
+ let bit_depth_luma_minus8 = null;
8759
+ let bit_depth_chroma_minus8 = null;
8760
+ let qpprime_y_zero_transform_bypass_flag = null;
8761
+ let log2_max_frame_num_minus4 = null;
8762
+ let log2_max_pic_order_cnt_lsb_minus4 = null;
8763
+ let max_num_ref_frames = null;
8764
+ let gaps_in_frame_num_value_allowed_flag = null;
8765
+ let mb_adaptive_frame_field_flag = null;
8766
+ let direct_8x8_inference_flag = null;
8767
+ let frame_crop_left_offset = null;
8768
+ let frame_crop_right_offset = null;
8769
+ let frame_crop_top_offset = null;
8770
+ let frame_crop_bottom_offset = null;
8771
+ let vui_parameters = null;
8772
+ 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)) {
8773
+ throw new Error("Invalid profile");
8774
+ }
8775
+ const chromaFormat = iterator.readExpGolomb();
8776
+ if (chromaFormat === 3) {
8777
+ separate_colour_plane_flag = iterator.getBits(1);
8778
+ }
8779
+ bit_depth_luma_minus8 = iterator.readExpGolomb();
8780
+ bit_depth_chroma_minus8 = iterator.readExpGolomb();
8781
+ qpprime_y_zero_transform_bypass_flag = iterator.getBits(1);
8782
+ const seq_scaling_matrix_present_flag = iterator.getBits(1);
8783
+ const seq_scaling_list_present_flag = [];
8784
+ if (seq_scaling_matrix_present_flag) {
8785
+ for (let i = 0;i < (chromaFormat !== 3 ? 8 : 12); i++) {
8786
+ seq_scaling_list_present_flag[i] = iterator.getBits(1);
8787
+ if (seq_scaling_list_present_flag[i]) {
8788
+ if (i < 6) {
8789
+ throw new Error("Not implemented");
8790
+ } else {
8791
+ throw new Error("Not implemented");
8792
+ }
8793
+ }
8794
+ }
8795
+ }
8796
+ log2_max_frame_num_minus4 = iterator.readExpGolomb();
8797
+ const pic_order_cnt_type = iterator.readExpGolomb();
8798
+ if (pic_order_cnt_type === 0) {
8799
+ log2_max_pic_order_cnt_lsb_minus4 = iterator.readExpGolomb();
8800
+ } else if (pic_order_cnt_type === 1) {
8801
+ throw new Error("pic_order_cnt_type = 1 not implemented");
8802
+ }
8803
+ max_num_ref_frames = iterator.readExpGolomb();
8804
+ gaps_in_frame_num_value_allowed_flag = iterator.getBits(1);
8805
+ const pic_width_in_mbs_minus1 = iterator.readExpGolomb();
8806
+ const pic_height_in_map_units_minus1 = iterator.readExpGolomb();
8807
+ const frame_mbs_only_flag = iterator.getBits(1);
8808
+ if (!frame_mbs_only_flag) {
8809
+ mb_adaptive_frame_field_flag = iterator.getBits(1);
8810
+ }
8811
+ direct_8x8_inference_flag = iterator.getBits(1);
8812
+ const frame_cropping_flag = iterator.getBits(1);
8813
+ if (frame_cropping_flag) {
8814
+ frame_crop_left_offset = iterator.readExpGolomb();
8815
+ frame_crop_right_offset = iterator.readExpGolomb();
8816
+ frame_crop_top_offset = iterator.readExpGolomb();
8817
+ frame_crop_bottom_offset = iterator.readExpGolomb();
8818
+ }
8819
+ const vui_parameters_present_flag = iterator.getBits(1);
8820
+ if (vui_parameters_present_flag) {
8821
+ vui_parameters = readVuiParameters(iterator);
8822
+ }
8823
+ iterator.stopReadingBits();
8562
8824
  return {
8563
8825
  profile,
8564
8826
  compatibility,
8565
- level
8827
+ level,
8828
+ bit_depth_chroma_minus8,
8829
+ bit_depth_luma_minus8,
8830
+ gaps_in_frame_num_value_allowed_flag,
8831
+ log2_max_frame_num_minus4,
8832
+ log2_max_pic_order_cnt_lsb_minus4,
8833
+ max_num_ref_frames,
8834
+ pic_height_in_map_units_minus1,
8835
+ pic_width_in_mbs_minus1,
8836
+ qpprime_y_zero_transform_bypass_flag,
8837
+ separate_colour_plane_flag,
8838
+ seq_parameter_set_id,
8839
+ direct_8x8_inference_flag,
8840
+ frame_crop_bottom_offset,
8841
+ frame_crop_left_offset,
8842
+ frame_crop_right_offset,
8843
+ frame_crop_top_offset,
8844
+ mb_adaptive_frame_field_flag,
8845
+ vui_parameters
8566
8846
  };
8567
8847
  };
8568
8848
  var findEnd = (buffer) => {
@@ -8590,11 +8870,9 @@ var inspect = (buffer) => {
8590
8870
  if (type === 7) {
8591
8871
  const end = findEnd(buffer);
8592
8872
  const data = readSps(iterator);
8593
- const sps = buffer.slice(1, end === null ? Infinity : end);
8873
+ const sps = buffer.slice(0, end === null ? Infinity : end);
8594
8874
  return {
8595
- level: data.level,
8596
- profile: data.profile,
8597
- compatibility: data.compatibility,
8875
+ spsData: data,
8598
8876
  sps,
8599
8877
  type: "avc-profile"
8600
8878
  };
@@ -8673,29 +8951,26 @@ var handleChunk = async ({
8673
8951
  const samplesPerSecond = strh.rate / strh.scale;
8674
8952
  const nthSample = options.parserState.getSamplesForTrack(trackId);
8675
8953
  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);
8954
+ const timestamp = Math.floor(timeInSec);
8955
+ const duration2 = Math.floor(1 / samplesPerSecond);
8678
8956
  const data = iterator.getSlice(ckSize);
8679
8957
  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
- }
8958
+ const keyOrDelta = getKeyFrameOrDeltaFromAvcInfo(infos);
8684
8959
  const avcProfile = infos.find((i) => i.type === "avc-profile");
8685
8960
  const ppsProfile = infos.find((i) => i.type === "avc-pps");
8686
8961
  if (avcProfile && ppsProfile) {
8687
8962
  await options.parserState.onProfile({ pps: ppsProfile, sps: avcProfile });
8688
8963
  options.parserState.tracks.setIsDone();
8689
8964
  }
8690
- await options.parserState.onVideoSample(trackId, {
8965
+ await options.parserState.onVideoSample(trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
8691
8966
  cts: timestamp,
8692
8967
  dts: timestamp,
8693
8968
  data,
8694
8969
  duration: duration2,
8695
8970
  timestamp,
8696
8971
  trackId,
8697
- type: keyOrDelta.type === "keyframe" ? "key" : "delta"
8698
- });
8972
+ type: keyOrDelta
8973
+ }, 1));
8699
8974
  return;
8700
8975
  }
8701
8976
  const audioChunk = ckId.match(/^([0-9]{2})wb$/);
@@ -8705,9 +8980,9 @@ var handleChunk = async ({
8705
8980
  const samplesPerSecond = strh.rate / strh.scale;
8706
8981
  const nthSample = options.parserState.getSamplesForTrack(trackId);
8707
8982
  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, {
8983
+ const timestamp = timeInSec;
8984
+ const duration2 = 1 / samplesPerSecond;
8985
+ await options.parserState.onAudioSample(trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
8711
8986
  cts: timestamp,
8712
8987
  dts: timestamp,
8713
8988
  data: iterator.getSlice(ckSize),
@@ -8715,7 +8990,7 @@ var handleChunk = async ({
8715
8990
  timestamp,
8716
8991
  trackId,
8717
8992
  type: "key"
8718
- });
8993
+ }, 1));
8719
8994
  }
8720
8995
  };
8721
8996
  var parseMovi = async ({
@@ -9201,8 +9476,8 @@ var parseRiffBody = async ({
9201
9476
  });
9202
9477
  await registerTrack({
9203
9478
  options,
9204
- state: options.parserState,
9205
- track: audioTrack
9479
+ track: audioTrack,
9480
+ container: "avi"
9206
9481
  });
9207
9482
  }
9208
9483
  if (options.onVideoTrack && strf.type === "strf-box-video") {
@@ -9213,8 +9488,8 @@ var parseRiffBody = async ({
9213
9488
  });
9214
9489
  registerVideoTrackWhenProfileIsAvailable({
9215
9490
  options,
9216
- state: options.parserState,
9217
- track: videoTrack
9491
+ track: videoTrack,
9492
+ container: "avi"
9218
9493
  });
9219
9494
  }
9220
9495
  options.nextTrackIndex++;
@@ -9250,15 +9525,758 @@ var parseRiff = ({
9250
9525
  return parseRiffBody({ iterator, structure, maxOffset: Infinity, options });
9251
9526
  };
9252
9527
 
9253
- // src/boxes/webm/segments/block-simple-block-flags.ts
9254
- var parseBlockFlags = (iterator, type) => {
9255
- if (type === matroskaElements.Block) {
9256
- iterator.startReadingBits();
9257
- iterator.getBits(4);
9258
- const invisible = Boolean(iterator.getBits(1));
9259
- const lacing = iterator.getBits(2);
9260
- iterator.getBits(1);
9261
- iterator.stopReadingBits();
9528
+ // src/boxes/transport-stream/next-pes-header-store.ts
9529
+ var makeNextPesHeaderStore = () => {
9530
+ let nextPesHeader = null;
9531
+ return {
9532
+ setNextPesHeader: (pesHeader) => {
9533
+ nextPesHeader = pesHeader;
9534
+ },
9535
+ getNextPesHeader: () => {
9536
+ if (!nextPesHeader) {
9537
+ throw new Error("No next PES header found");
9538
+ }
9539
+ return nextPesHeader;
9540
+ }
9541
+ };
9542
+ };
9543
+
9544
+ // src/boxes/transport-stream/discard-rest-of-packet.ts
9545
+ var discardRestOfPacket = (iterator) => {
9546
+ const next188 = 188 - iterator.counter.getOffset() % 188;
9547
+ iterator.discard(next188);
9548
+ };
9549
+ var getRestOfPacket = (iterator) => {
9550
+ const next188 = 188 - iterator.counter.getOffset() % 188;
9551
+ return iterator.getSlice(next188);
9552
+ };
9553
+
9554
+ // src/boxes/transport-stream/parse-pat.ts
9555
+ var parsePatTable = (iterator, tableId) => {
9556
+ iterator.getUint16();
9557
+ iterator.startReadingBits();
9558
+ iterator.getBits(7);
9559
+ iterator.getBits(1);
9560
+ const sectionNumber = iterator.getBits(8);
9561
+ const lastSectionNumber = iterator.getBits(8);
9562
+ if (tableId !== 0) {
9563
+ throw new Error("Invalid table ID: " + tableId);
9564
+ }
9565
+ const tables = [];
9566
+ for (let i = sectionNumber;i <= lastSectionNumber; i++) {
9567
+ const programNumber = iterator.getBits(16);
9568
+ iterator.getBits(3);
9569
+ const programMapIdentifier = iterator.getBits(13);
9570
+ tables.push({
9571
+ type: "transport-stream-program-association-table",
9572
+ programNumber,
9573
+ programMapIdentifier
9574
+ });
9575
+ }
9576
+ iterator.stopReadingBits();
9577
+ return {
9578
+ type: "transport-stream-pat-box",
9579
+ tableId: tableId.toString(16),
9580
+ pat: tables
9581
+ };
9582
+ };
9583
+ var parsePat = (iterator) => {
9584
+ iterator.startReadingBits();
9585
+ const tableId = iterator.getBits(8);
9586
+ iterator.getBits(1);
9587
+ iterator.getBits(1);
9588
+ iterator.getBits(4);
9589
+ const sectionLength = iterator.getBits(10);
9590
+ if (sectionLength > 1021) {
9591
+ throw new Error("Invalid section length");
9592
+ }
9593
+ iterator.stopReadingBits();
9594
+ const tables = parsePatTable(iterator, tableId);
9595
+ discardRestOfPacket(iterator);
9596
+ return tables;
9597
+ };
9598
+
9599
+ // src/boxes/transport-stream/parse-pes.ts
9600
+ var parsePes = (iterator) => {
9601
+ const ident = iterator.getUint24();
9602
+ if (ident !== 1) {
9603
+ throw new Error(`Unexpected PES packet start code: ${ident.toString(16)}`);
9604
+ }
9605
+ const streamId = iterator.getUint8();
9606
+ iterator.getUint16();
9607
+ iterator.startReadingBits();
9608
+ const markerBits = iterator.getBits(2);
9609
+ if (markerBits !== 2) {
9610
+ throw new Error(`Invalid marker bits: ${markerBits}`);
9611
+ }
9612
+ const scrambled = iterator.getBits(2);
9613
+ if (scrambled !== 0) {
9614
+ throw new Error(`Only supporting non-scrambled streams`);
9615
+ }
9616
+ const priority = iterator.getBits(1);
9617
+ iterator.getBits(1);
9618
+ iterator.getBits(1);
9619
+ iterator.getBits(1);
9620
+ const ptsPresent = iterator.getBits(1);
9621
+ const dtsPresent = iterator.getBits(1);
9622
+ if (!ptsPresent && dtsPresent) {
9623
+ throw new Error(`DTS is present but not PTS, this is not allowed in the spec`);
9624
+ }
9625
+ iterator.getBits(1);
9626
+ iterator.getBits(1);
9627
+ iterator.getBits(1);
9628
+ iterator.getBits(1);
9629
+ iterator.getBits(1);
9630
+ iterator.getBits(1);
9631
+ const pesHeaderLength = iterator.getBits(8);
9632
+ const offset = iterator.counter.getOffset();
9633
+ let pts = null;
9634
+ if (!ptsPresent) {
9635
+ throw new Error(`PTS is required`);
9636
+ }
9637
+ const fourBits = iterator.getBits(4);
9638
+ if (fourBits !== 3 && fourBits !== 2) {
9639
+ throw new Error(`Invalid PTS marker bits: ${fourBits}`);
9640
+ }
9641
+ const pts1 = iterator.getBits(3);
9642
+ iterator.getBits(1);
9643
+ const pts2 = iterator.getBits(15);
9644
+ iterator.getBits(1);
9645
+ const pts3 = iterator.getBits(15);
9646
+ iterator.getBits(1);
9647
+ pts = pts1 << 30 | pts2 << 15 | pts3;
9648
+ let dts = null;
9649
+ if (dtsPresent) {
9650
+ const _fourBits = iterator.getBits(4);
9651
+ if (_fourBits !== 1) {
9652
+ throw new Error(`Invalid DTS marker bits: ${_fourBits}`);
9653
+ }
9654
+ const dts1 = iterator.getBits(3);
9655
+ iterator.getBits(1);
9656
+ const dts2 = iterator.getBits(15);
9657
+ iterator.getBits(1);
9658
+ const dts3 = iterator.getBits(15);
9659
+ iterator.getBits(1);
9660
+ dts = dts1 << 30 | dts2 << 15 | dts3;
9661
+ }
9662
+ iterator.stopReadingBits();
9663
+ iterator.discard(pesHeaderLength - (iterator.counter.getOffset() - offset));
9664
+ const packet = {
9665
+ dts,
9666
+ pts,
9667
+ streamId,
9668
+ priority
9669
+ };
9670
+ return packet;
9671
+ };
9672
+
9673
+ // src/boxes/transport-stream/parse-pmt.ts
9674
+ var parsePmtTable = ({
9675
+ iterator,
9676
+ tableId,
9677
+ sectionLength
9678
+ }) => {
9679
+ const start = iterator.counter.getOffset();
9680
+ iterator.getUint16();
9681
+ iterator.startReadingBits();
9682
+ iterator.getBits(7);
9683
+ iterator.getBits(1);
9684
+ const sectionNumber = iterator.getBits(8);
9685
+ const lastSectionNumber = iterator.getBits(8);
9686
+ const tables = [];
9687
+ for (let i = sectionNumber;i <= lastSectionNumber; i++) {
9688
+ iterator.getBits(3);
9689
+ iterator.getBits(13);
9690
+ iterator.getBits(4);
9691
+ const programInfoLength = iterator.getBits(12);
9692
+ const streams = [];
9693
+ while (true) {
9694
+ const streamType = iterator.getBits(8);
9695
+ iterator.getBits(3);
9696
+ const elementaryPid = iterator.getBits(13);
9697
+ iterator.getBits(4);
9698
+ const esInfoLength = iterator.getBits(12);
9699
+ iterator.getBits(esInfoLength * 8);
9700
+ streams.push({ streamType, pid: elementaryPid });
9701
+ iterator.getBits(programInfoLength * 8);
9702
+ const remaining = sectionLength - (iterator.counter.getOffset() - start);
9703
+ if (remaining <= 4) {
9704
+ break;
9705
+ }
9706
+ }
9707
+ tables.push({
9708
+ type: "transport-stream-program-map-table",
9709
+ streams
9710
+ });
9711
+ }
9712
+ if (tables.length !== 1) {
9713
+ throw new Error("Does not PMT table with more than 1 entry, uncommon");
9714
+ }
9715
+ iterator.stopReadingBits();
9716
+ return {
9717
+ type: "transport-stream-pmt-box",
9718
+ tableId,
9719
+ streams: tables[0].streams
9720
+ };
9721
+ };
9722
+ var parsePmt = (iterator) => {
9723
+ iterator.startReadingBits();
9724
+ const tableId = iterator.getBits(8);
9725
+ iterator.getBits(1);
9726
+ iterator.getBits(1);
9727
+ iterator.getBits(4);
9728
+ const sectionLength = iterator.getBits(10);
9729
+ if (sectionLength > 1021) {
9730
+ throw new Error("Invalid section length");
9731
+ }
9732
+ iterator.stopReadingBits();
9733
+ const tables = parsePmtTable({ iterator, tableId, sectionLength });
9734
+ discardRestOfPacket(iterator);
9735
+ return tables;
9736
+ };
9737
+
9738
+ // src/boxes/transport-stream/adts-header.ts
9739
+ var readAdtsHeader = (buffer) => {
9740
+ if (buffer.byteLength < 9) {
9741
+ return null;
9742
+ }
9743
+ const iterator = getArrayBufferIterator(buffer, buffer.byteLength);
9744
+ iterator.startReadingBits();
9745
+ const bits = iterator.getBits(12);
9746
+ if (bits !== 4095) {
9747
+ throw new Error("Invalid ADTS header ");
9748
+ }
9749
+ const id = iterator.getBits(1);
9750
+ if (id !== 0) {
9751
+ throw new Error("Only supporting MPEG-4 for .ts");
9752
+ }
9753
+ const layer = iterator.getBits(2);
9754
+ if (layer !== 0) {
9755
+ throw new Error("Only supporting layer 0 for .ts");
9756
+ }
9757
+ const protectionAbsent = iterator.getBits(1);
9758
+ const audioObjectType = iterator.getBits(2);
9759
+ const samplingFrequencyIndex = iterator.getBits(4);
9760
+ const sampleRate = getSampleRateFromSampleFrequencyIndex(samplingFrequencyIndex);
9761
+ iterator.getBits(1);
9762
+ const channelConfiguration = iterator.getBits(3);
9763
+ const codecPrivate2 = createAacCodecPrivate({
9764
+ audioObjectType,
9765
+ sampleRate,
9766
+ channelConfiguration
9767
+ });
9768
+ iterator.getBits(1);
9769
+ iterator.getBits(1);
9770
+ iterator.getBits(1);
9771
+ iterator.getBits(1);
9772
+ const frameLength = iterator.getBits(13);
9773
+ iterator.getBits(11);
9774
+ iterator.getBits(2);
9775
+ if (!protectionAbsent) {
9776
+ iterator.getBits(16);
9777
+ }
9778
+ iterator.stopReadingBits();
9779
+ iterator.destroy();
9780
+ return {
9781
+ frameLength,
9782
+ codecPrivate: codecPrivate2,
9783
+ channelConfiguration,
9784
+ sampleRate,
9785
+ audioObjectType
9786
+ };
9787
+ };
9788
+
9789
+ // src/boxes/transport-stream/find-separator.ts
9790
+ function findSubarrayIndex(array, subarray) {
9791
+ const subarrayLength = subarray.length;
9792
+ const arrayLength = array.length;
9793
+ for (let i = 0;i <= arrayLength - subarrayLength; i++) {
9794
+ let match = true;
9795
+ for (let j = 0;j < subarrayLength; j++) {
9796
+ if (array[i + j] !== subarray[j]) {
9797
+ match = false;
9798
+ break;
9799
+ }
9800
+ }
9801
+ if (match) {
9802
+ if (subarray[i - 1] === 0) {
9803
+ i--;
9804
+ }
9805
+ return i;
9806
+ }
9807
+ }
9808
+ return -1;
9809
+ }
9810
+ var findNextSeparator = (restOfPacket, transportStreamEntry) => {
9811
+ if (transportStreamEntry.streamType === 27) {
9812
+ return findSubarrayIndex(restOfPacket, new Uint8Array([0, 0, 1, 9]));
9813
+ }
9814
+ throw new Error(`Unsupported stream ID ${transportStreamEntry.streamType}`);
9815
+ };
9816
+
9817
+ // src/boxes/avc/interpret-sps.ts
9818
+ var getDimensionsFromSps = (sps) => {
9819
+ const height = sps.pic_height_in_map_units_minus1;
9820
+ const width = sps.pic_width_in_mbs_minus1;
9821
+ return {
9822
+ height: (height + 1) * 16,
9823
+ width: (width + 1) * 16
9824
+ };
9825
+ };
9826
+ var getSampleAspectRatioFromSps = (sps) => {
9827
+ if (sps.vui_parameters?.sar_height && sps.vui_parameters.sar_width) {
9828
+ return {
9829
+ width: sps.vui_parameters.sar_width,
9830
+ height: sps.vui_parameters.sar_height
9831
+ };
9832
+ }
9833
+ return {
9834
+ width: 1,
9835
+ height: 1
9836
+ };
9837
+ };
9838
+ var getVideoColorFromSps = (sps) => {
9839
+ const matrixCoefficients2 = sps.vui_parameters?.matrix_coefficients;
9840
+ const transferCharacteristics2 = sps.vui_parameters?.transfer_characteristics;
9841
+ const colorPrimaries = sps.vui_parameters?.colour_primaries;
9842
+ return {
9843
+ matrixCoefficients: matrixCoefficients2 ? getMatrixCoefficientsFromIndex(matrixCoefficients2) : null,
9844
+ transferCharacteristics: transferCharacteristics2 ? getTransferCharacteristicsFromIndex(transferCharacteristics2) : null,
9845
+ primaries: colorPrimaries ? getPrimariesFromIndex(colorPrimaries) : null,
9846
+ fullRange: sps.vui_parameters?.video_full_range_flag ?? null
9847
+ };
9848
+ };
9849
+
9850
+ // src/boxes/avc/sps-and-pps.ts
9851
+ var getSpsAndPps = (infos) => {
9852
+ const avcProfile = infos.find((i) => i.type === "avc-profile");
9853
+ const ppsProfile = infos.find((i) => i.type === "avc-pps");
9854
+ if (!avcProfile || !ppsProfile) {
9855
+ throw new Error("Expected avcProfile and ppsProfile");
9856
+ }
9857
+ return { pps: ppsProfile, sps: avcProfile };
9858
+ };
9859
+
9860
+ // src/boxes/transport-stream/handle-avc-packet.ts
9861
+ var MPEG_TIMESCALE = 90000;
9862
+ var handleAvcPacket = async ({
9863
+ streamBuffer,
9864
+ programId,
9865
+ options
9866
+ }) => {
9867
+ const avc = parseAvc(streamBuffer.buffer);
9868
+ const isTrackRegistered = options.parserState.tracks.getTracks().find((t) => {
9869
+ return t.trackId === programId;
9870
+ });
9871
+ if (!isTrackRegistered) {
9872
+ const spsAndPps = getSpsAndPps(avc);
9873
+ const dimensions = getDimensionsFromSps(spsAndPps.sps.spsData);
9874
+ const sampleAspectRatio = getSampleAspectRatioFromSps(spsAndPps.sps.spsData);
9875
+ const track = {
9876
+ rotation: 0,
9877
+ trackId: programId,
9878
+ type: "video",
9879
+ timescale: MPEG_TIMESCALE,
9880
+ codec: getCodecStringFromSpsAndPps(spsAndPps.sps),
9881
+ codecPrivate: getAvccBoxContent(spsAndPps),
9882
+ fps: null,
9883
+ codedWidth: dimensions.width,
9884
+ codedHeight: dimensions.height,
9885
+ height: dimensions.height,
9886
+ width: dimensions.width,
9887
+ displayAspectWidth: dimensions.width,
9888
+ displayAspectHeight: dimensions.height,
9889
+ trakBox: null,
9890
+ codecWithoutConfig: "h264",
9891
+ description: undefined,
9892
+ sampleAspectRatio: {
9893
+ denominator: sampleAspectRatio.height,
9894
+ numerator: sampleAspectRatio.width
9895
+ },
9896
+ color: getVideoColorFromSps(spsAndPps.sps.spsData)
9897
+ };
9898
+ await registerTrack({ track, options, container: "transport-stream" });
9899
+ }
9900
+ const sample = {
9901
+ cts: streamBuffer.pesHeader.pts,
9902
+ dts: streamBuffer.pesHeader.dts ?? streamBuffer.pesHeader.pts,
9903
+ timestamp: streamBuffer.pesHeader.pts,
9904
+ duration: undefined,
9905
+ data: new Uint8Array(streamBuffer.buffer),
9906
+ trackId: programId,
9907
+ type: getKeyFrameOrDeltaFromAvcInfo(avc)
9908
+ };
9909
+ await options.parserState.onVideoSample(programId, convertAudioOrVideoSampleToWebCodecsTimestamps(sample, MPEG_TIMESCALE));
9910
+ };
9911
+
9912
+ // src/boxes/transport-stream/handle-aac-packet.ts
9913
+ var handleAacPacket = async ({
9914
+ streamBuffer,
9915
+ options,
9916
+ programId
9917
+ }) => {
9918
+ const adtsHeader = readAdtsHeader(streamBuffer.buffer);
9919
+ if (!adtsHeader) {
9920
+ throw new Error("Invalid ADTS header - too short");
9921
+ }
9922
+ const { channelConfiguration, codecPrivate: codecPrivate2, sampleRate, audioObjectType } = adtsHeader;
9923
+ const isTrackRegistered = options.parserState.tracks.getTracks().find((t) => {
9924
+ return t.trackId === programId;
9925
+ });
9926
+ if (!isTrackRegistered) {
9927
+ const track = {
9928
+ type: "audio",
9929
+ codecPrivate: codecPrivate2,
9930
+ trackId: programId,
9931
+ trakBox: null,
9932
+ timescale: MPEG_TIMESCALE,
9933
+ codecWithoutConfig: "aac",
9934
+ codec: mapAudioObjectTypeToCodecString(audioObjectType),
9935
+ description: undefined,
9936
+ numberOfChannels: channelConfiguration,
9937
+ sampleRate
9938
+ };
9939
+ await registerTrack({
9940
+ track,
9941
+ options,
9942
+ container: "transport-stream"
9943
+ });
9944
+ }
9945
+ const sample = {
9946
+ cts: streamBuffer.pesHeader.pts,
9947
+ dts: streamBuffer.pesHeader.dts ?? streamBuffer.pesHeader.pts,
9948
+ timestamp: streamBuffer.pesHeader.pts,
9949
+ duration: undefined,
9950
+ data: new Uint8Array(streamBuffer.buffer),
9951
+ trackId: programId,
9952
+ type: "key"
9953
+ };
9954
+ await options.parserState.onAudioSample(programId, convertAudioOrVideoSampleToWebCodecsTimestamps(sample, MPEG_TIMESCALE));
9955
+ };
9956
+
9957
+ // src/boxes/transport-stream/process-stream-buffers.ts
9958
+ var processStreamBuffer = async ({
9959
+ streamBuffer,
9960
+ options,
9961
+ programId,
9962
+ structure
9963
+ }) => {
9964
+ const stream = getStreamForId(structure, programId);
9965
+ if (!stream) {
9966
+ throw new Error("No stream found");
9967
+ }
9968
+ if (stream.streamType === 27) {
9969
+ await handleAvcPacket({ programId, streamBuffer, options });
9970
+ } else if (stream.streamType === 15) {
9971
+ await handleAacPacket({ streamBuffer, options, programId });
9972
+ }
9973
+ if (!options.parserState.tracks.hasAllTracks()) {
9974
+ const tracksRegistered = options.parserState.tracks.getTracks().length;
9975
+ const { streams } = findProgramMapTableOrThrow(structure);
9976
+ if (streams.length === tracksRegistered) {
9977
+ options.parserState.tracks.setIsDone();
9978
+ }
9979
+ }
9980
+ };
9981
+ var processFinalStreamBuffers = async ({
9982
+ streamBufferMap,
9983
+ parserContext,
9984
+ structure
9985
+ }) => {
9986
+ for (const [programId, buffer] of streamBufferMap) {
9987
+ if (buffer.buffer.byteLength > 0) {
9988
+ await processStreamBuffer({
9989
+ streamBuffer: buffer,
9990
+ options: parserContext,
9991
+ programId,
9992
+ structure
9993
+ });
9994
+ streamBufferMap.delete(programId);
9995
+ }
9996
+ }
9997
+ };
9998
+
9999
+ // src/boxes/transport-stream/parse-stream-packet.ts
10000
+ var parseAdtsStream = async ({
10001
+ restOfPacket,
10002
+ transportStreamEntry,
10003
+ streamBuffers,
10004
+ nextPesHeader,
10005
+ options,
10006
+ structure
10007
+ }) => {
10008
+ const streamBuffer = streamBuffers.get(transportStreamEntry.pid);
10009
+ if (!streamBuffer) {
10010
+ streamBuffers.set(transportStreamEntry.pid, {
10011
+ buffer: restOfPacket,
10012
+ pesHeader: nextPesHeader
10013
+ });
10014
+ return;
10015
+ }
10016
+ const expectedLength = readAdtsHeader(streamBuffer.buffer)?.frameLength ?? null;
10017
+ const bytesToTake = expectedLength ? Math.min(restOfPacket.length, expectedLength - streamBuffer.buffer.byteLength) : restOfPacket.length;
10018
+ streamBuffer.buffer = combineUint8Arrays([
10019
+ streamBuffer.buffer,
10020
+ restOfPacket.slice(0, bytesToTake)
10021
+ ]);
10022
+ if (expectedLength === streamBuffer.buffer.byteLength) {
10023
+ await processStreamBuffer({
10024
+ streamBuffer,
10025
+ programId: transportStreamEntry.pid,
10026
+ options,
10027
+ structure
10028
+ });
10029
+ const rest = restOfPacket.slice(bytesToTake);
10030
+ streamBuffers.set(transportStreamEntry.pid, {
10031
+ buffer: rest,
10032
+ pesHeader: nextPesHeader
10033
+ });
10034
+ }
10035
+ };
10036
+ var parseAvcStream = async ({
10037
+ restOfPacket,
10038
+ transportStreamEntry,
10039
+ streamBuffers,
10040
+ nextPesHeader,
10041
+ programId,
10042
+ parserContext,
10043
+ structure
10044
+ }) => {
10045
+ const indexOfSeparator = findNextSeparator(restOfPacket, transportStreamEntry);
10046
+ const streamBuffer = streamBuffers.get(transportStreamEntry.pid);
10047
+ if (indexOfSeparator === -1) {
10048
+ if (streamBuffer) {
10049
+ streamBuffer.buffer = combineUint8Arrays([
10050
+ streamBuffer.buffer,
10051
+ restOfPacket
10052
+ ]);
10053
+ return;
10054
+ }
10055
+ streamBuffers.set(programId, {
10056
+ pesHeader: nextPesHeader,
10057
+ buffer: restOfPacket
10058
+ });
10059
+ return;
10060
+ }
10061
+ if (streamBuffer) {
10062
+ const packet = restOfPacket.slice(0, indexOfSeparator);
10063
+ streamBuffer.buffer = combineUint8Arrays([streamBuffer.buffer, packet]);
10064
+ await processStreamBuffer({
10065
+ options: parserContext,
10066
+ streamBuffer,
10067
+ programId,
10068
+ structure
10069
+ });
10070
+ const rest = restOfPacket.slice(indexOfSeparator);
10071
+ streamBuffers.set(programId, {
10072
+ pesHeader: nextPesHeader,
10073
+ buffer: rest
10074
+ });
10075
+ return;
10076
+ }
10077
+ if (indexOfSeparator !== 0) {
10078
+ throw new Error("No stream buffer found but new separator is not at the beginning");
10079
+ }
10080
+ streamBuffers.set(programId, {
10081
+ pesHeader: nextPesHeader,
10082
+ buffer: restOfPacket.slice(indexOfSeparator)
10083
+ });
10084
+ };
10085
+ var parseStream = ({
10086
+ iterator,
10087
+ transportStreamEntry,
10088
+ streamBuffers,
10089
+ parserContext,
10090
+ programId,
10091
+ structure,
10092
+ nextPesHeader
10093
+ }) => {
10094
+ const restOfPacket = getRestOfPacket(iterator);
10095
+ if (transportStreamEntry.streamType === 27) {
10096
+ return parseAvcStream({
10097
+ restOfPacket,
10098
+ transportStreamEntry,
10099
+ streamBuffers,
10100
+ nextPesHeader,
10101
+ parserContext,
10102
+ programId,
10103
+ structure
10104
+ });
10105
+ }
10106
+ if (transportStreamEntry.streamType === 15) {
10107
+ return parseAdtsStream({
10108
+ restOfPacket,
10109
+ transportStreamEntry,
10110
+ streamBuffers,
10111
+ nextPesHeader,
10112
+ options: parserContext,
10113
+ structure
10114
+ });
10115
+ }
10116
+ throw new Error(`Unsupported stream type ${transportStreamEntry.streamType}`);
10117
+ };
10118
+
10119
+ // src/boxes/transport-stream/parse-packet.ts
10120
+ var parsePacket = async ({
10121
+ iterator,
10122
+ structure,
10123
+ streamBuffers,
10124
+ parserContext,
10125
+ nextPesHeaderStore
10126
+ }) => {
10127
+ const offset = iterator.counter.getOffset();
10128
+ const syncByte = iterator.getUint8();
10129
+ if (syncByte !== 71) {
10130
+ throw new Error("Invalid sync byte");
10131
+ }
10132
+ iterator.startReadingBits();
10133
+ iterator.getBits(1);
10134
+ const payloadUnitStartIndicator = iterator.getBits(1);
10135
+ iterator.getBits(1);
10136
+ const programId = iterator.getBits(13);
10137
+ iterator.getBits(2);
10138
+ const adaptationFieldControl1 = iterator.getBits(1);
10139
+ iterator.getBits(1);
10140
+ iterator.getBits(4);
10141
+ iterator.stopReadingBits();
10142
+ if (adaptationFieldControl1 === 1) {
10143
+ iterator.startReadingBits();
10144
+ const adaptationFieldLength = iterator.getBits(8);
10145
+ const headerOffset = iterator.counter.getOffset();
10146
+ if (adaptationFieldLength > 0) {
10147
+ iterator.getBits(1);
10148
+ iterator.getBits(1);
10149
+ iterator.getBits(1);
10150
+ iterator.getBits(1);
10151
+ iterator.getBits(1);
10152
+ iterator.getBits(1);
10153
+ iterator.getBits(1);
10154
+ iterator.getBits(1);
10155
+ }
10156
+ const remaining = adaptationFieldLength - (iterator.counter.getOffset() - headerOffset);
10157
+ iterator.stopReadingBits();
10158
+ const toDiscard = Math.max(0, remaining);
10159
+ iterator.discard(toDiscard);
10160
+ }
10161
+ const read = iterator.counter.getOffset() - offset;
10162
+ if (read === 188) {
10163
+ return Promise.resolve(null);
10164
+ }
10165
+ const pat = structure.boxes.find((b) => b.type === "transport-stream-pmt-box");
10166
+ const isPes = payloadUnitStartIndicator && pat?.streams.find((e) => e.pid === programId);
10167
+ if (isPes) {
10168
+ const packetPes = parsePes(iterator);
10169
+ nextPesHeaderStore.setNextPesHeader(packetPes);
10170
+ } else if (payloadUnitStartIndicator === 1) {
10171
+ iterator.getUint8();
10172
+ }
10173
+ if (programId === 0) {
10174
+ return Promise.resolve(parsePat(iterator));
10175
+ }
10176
+ const program = getProgramForId(structure, programId);
10177
+ if (program) {
10178
+ const pmt = parsePmt(iterator);
10179
+ return Promise.resolve(pmt);
10180
+ }
10181
+ const stream = getStreamForId(structure, programId);
10182
+ if (stream) {
10183
+ await parseStream({
10184
+ iterator,
10185
+ transportStreamEntry: stream,
10186
+ streamBuffers,
10187
+ nextPesHeader: nextPesHeaderStore.getNextPesHeader(),
10188
+ parserContext,
10189
+ programId,
10190
+ structure
10191
+ });
10192
+ return Promise.resolve(null);
10193
+ }
10194
+ throw new Error("Unknown packet identifier");
10195
+ };
10196
+
10197
+ // src/boxes/transport-stream/parse-transport-stream.ts
10198
+ var parseTransportStream = async ({
10199
+ iterator,
10200
+ parserContext,
10201
+ structure,
10202
+ streamBuffers,
10203
+ fields,
10204
+ nextPesHeaderStore
10205
+ }) => {
10206
+ if (iterator.bytesRemaining() === 0) {
10207
+ await processFinalStreamBuffers({
10208
+ streamBufferMap: streamBuffers,
10209
+ parserContext,
10210
+ structure
10211
+ });
10212
+ return Promise.resolve({
10213
+ status: "done",
10214
+ segments: structure
10215
+ });
10216
+ }
10217
+ while (true) {
10218
+ if (hasAllInfo({
10219
+ fields,
10220
+ state: parserContext.parserState,
10221
+ structure
10222
+ })) {
10223
+ break;
10224
+ }
10225
+ if (iterator.bytesRemaining() < 188) {
10226
+ return Promise.resolve({
10227
+ status: "incomplete",
10228
+ segments: structure,
10229
+ skipTo: null,
10230
+ continueParsing: () => {
10231
+ return parseTransportStream({
10232
+ iterator,
10233
+ parserContext,
10234
+ structure,
10235
+ streamBuffers,
10236
+ fields,
10237
+ nextPesHeaderStore
10238
+ });
10239
+ }
10240
+ });
10241
+ }
10242
+ const packet = await parsePacket({
10243
+ iterator,
10244
+ structure,
10245
+ streamBuffers,
10246
+ parserContext,
10247
+ nextPesHeaderStore
10248
+ });
10249
+ if (packet) {
10250
+ structure.boxes.push(packet);
10251
+ break;
10252
+ }
10253
+ }
10254
+ return Promise.resolve({
10255
+ segments: structure,
10256
+ status: "incomplete",
10257
+ continueParsing() {
10258
+ return parseTransportStream({
10259
+ iterator,
10260
+ parserContext,
10261
+ structure,
10262
+ streamBuffers,
10263
+ fields,
10264
+ nextPesHeaderStore
10265
+ });
10266
+ },
10267
+ skipTo: null
10268
+ });
10269
+ };
10270
+
10271
+ // src/boxes/webm/segments/block-simple-block-flags.ts
10272
+ var parseBlockFlags = (iterator, type) => {
10273
+ if (type === matroskaElements.Block) {
10274
+ iterator.startReadingBits();
10275
+ iterator.getBits(4);
10276
+ const invisible = Boolean(iterator.getBits(1));
10277
+ const lacing = iterator.getBits(2);
10278
+ iterator.getBits(1);
10279
+ iterator.stopReadingBits();
9262
10280
  return {
9263
10281
  invisible,
9264
10282
  lacing,
@@ -9456,9 +10474,9 @@ var postprocessEbml = async ({
9456
10474
  });
9457
10475
  if (track) {
9458
10476
  await registerTrack({
9459
- state: parserContext.parserState,
9460
10477
  options: parserContext,
9461
- track
10478
+ track,
10479
+ container: "webm"
9462
10480
  });
9463
10481
  }
9464
10482
  }
@@ -9928,6 +10946,19 @@ var parseVideo = ({
9928
10946
  Log.verbose(logLevel, "Detected Matroska container");
9929
10947
  return parseWebm({ counter: iterator, parserContext: options, fields });
9930
10948
  }
10949
+ if (iterator.isTransportStream()) {
10950
+ return parseTransportStream({
10951
+ iterator,
10952
+ parserContext: options,
10953
+ structure: {
10954
+ type: "transport-stream",
10955
+ boxes: []
10956
+ },
10957
+ streamBuffers: new Map,
10958
+ fields,
10959
+ nextPesHeaderStore: makeNextPesHeaderStore()
10960
+ });
10961
+ }
9931
10962
  if (iterator.isMp3()) {
9932
10963
  return Promise.reject(new Error("MP3 files are not yet supported"));
9933
10964
  }
@@ -9971,12 +11002,17 @@ var makeCanSkipTracksState = ({
9971
11002
 
9972
11003
  // src/state/has-tracks-section.ts
9973
11004
  var makeTracksSectionState = (canSkipTracksState) => {
11005
+ const tracks2 = [];
9974
11006
  let doneWithTracks = false;
9975
11007
  return {
9976
11008
  hasAllTracks: () => doneWithTracks,
9977
11009
  setIsDone: () => {
9978
11010
  doneWithTracks = true;
9979
11011
  },
11012
+ addTrack: (track) => {
11013
+ tracks2.push(track);
11014
+ },
11015
+ getTracks: () => tracks2,
9980
11016
  ensureHasTracksAtEnd: () => {
9981
11017
  if (canSkipTracksState.canSkipTracks()) {
9982
11018
  return;
@@ -10199,10 +11235,10 @@ var parseMedia = async ({
10199
11235
  };
10200
11236
  triggerInfoEmit();
10201
11237
  while (parseResult === null || parseResult.status === "incomplete") {
10202
- if (signal?.aborted) {
10203
- throw new Error("Aborted");
10204
- }
10205
11238
  while (true) {
11239
+ if (signal?.aborted) {
11240
+ throw new Error("Aborted");
11241
+ }
10206
11242
  const result = await currentReader.reader.read();
10207
11243
  if (iterator) {
10208
11244
  if (!result.done) {