@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.
- package/dist/aac-codecprivate.d.ts +2 -9
- package/dist/aac-codecprivate.js +69 -34
- package/dist/add-avc-profile-to-track.js +4 -23
- package/dist/boxes/avc/codec-private.d.ts +2 -0
- package/dist/boxes/avc/codec-private.js +28 -0
- package/dist/boxes/avc/codec-string.d.ts +2 -0
- package/dist/boxes/avc/codec-string.js +7 -0
- package/dist/boxes/avc/color.d.ts +6 -0
- package/dist/boxes/avc/color.js +39 -0
- package/dist/boxes/avc/interpret-sps.d.ts +11 -0
- package/dist/boxes/avc/interpret-sps.js +44 -0
- package/dist/boxes/avc/key.d.ts +2 -0
- package/dist/boxes/avc/key.js +11 -0
- package/dist/boxes/avc/parse-avc.d.ts +36 -3
- package/dist/boxes/avc/parse-avc.js +161 -4
- package/dist/boxes/avc/sps-and-pps.d.ts +3 -0
- package/dist/boxes/avc/sps-and-pps.js +12 -0
- package/dist/boxes/iso-base-media/get-video-codec-from-iso-track.d.ts +2 -0
- package/dist/boxes/iso-base-media/get-video-codec-from-iso-track.js +55 -0
- package/dist/boxes/iso-base-media/make-track.js +2 -1
- package/dist/boxes/iso-base-media/mdat/mdat.js +8 -14
- package/dist/boxes/iso-base-media/process-box.js +1 -1
- package/dist/boxes/riff/parse-box.js +2 -2
- package/dist/boxes/riff/parse-movi.js +12 -14
- package/dist/boxes/transport-stream/adts-header.d.ts +7 -0
- package/dist/boxes/transport-stream/adts-header.js +56 -0
- package/dist/boxes/transport-stream/boxes.d.ts +41 -0
- package/dist/boxes/transport-stream/boxes.js +2 -0
- package/dist/boxes/transport-stream/discard-rest-of-packet.d.ts +3 -0
- package/dist/boxes/transport-stream/discard-rest-of-packet.js +13 -0
- package/dist/boxes/transport-stream/find-separator.d.ts +2 -0
- package/dist/boxes/transport-stream/find-separator.js +30 -0
- package/dist/boxes/transport-stream/get-tracks.d.ts +5 -0
- package/dist/boxes/transport-stream/get-tracks.js +33 -0
- package/dist/boxes/transport-stream/handle-aac-packet.d.ts +7 -0
- package/dist/boxes/transport-stream/handle-aac-packet.js +50 -0
- package/dist/boxes/transport-stream/handle-avc-packet.d.ts +8 -0
- package/dist/boxes/transport-stream/handle-avc-packet.js +60 -0
- package/dist/boxes/transport-stream/next-pes-header-store.d.ts +6 -0
- package/dist/boxes/transport-stream/next-pes-header-store.js +18 -0
- package/dist/boxes/transport-stream/parse-packet.d.ts +13 -0
- package/dist/boxes/transport-stream/parse-packet.js +80 -0
- package/dist/boxes/transport-stream/parse-pat.d.ts +8 -0
- package/dist/boxes/transport-stream/parse-pat.js +49 -0
- package/dist/boxes/transport-stream/parse-pes.d.ts +8 -0
- package/dist/boxes/transport-stream/parse-pes.js +76 -0
- package/dist/boxes/transport-stream/parse-pmt.d.ts +11 -0
- package/dist/boxes/transport-stream/parse-pmt.js +64 -0
- package/dist/boxes/transport-stream/parse-stream-packet.d.ts +15 -0
- package/dist/boxes/transport-stream/parse-stream-packet.js +107 -0
- package/dist/boxes/transport-stream/parse-transport-stream.d.ts +14 -0
- package/dist/boxes/transport-stream/parse-transport-stream.js +72 -0
- package/dist/boxes/transport-stream/process-stream-buffers.d.ts +19 -0
- package/dist/boxes/transport-stream/process-stream-buffers.js +42 -0
- package/dist/boxes/transport-stream/traversal.d.ts +6 -0
- package/dist/boxes/transport-stream/traversal.js +30 -0
- package/dist/boxes/webm/ebml.d.ts +1 -1
- package/dist/boxes/webm/parse-ebml.js +1 -1
- package/dist/buffer-iterator.d.ts +2 -0
- package/dist/buffer-iterator.js +25 -0
- package/dist/convert-audio-or-video-sample.d.ts +2 -0
- package/dist/convert-audio-or-video-sample.js +17 -0
- package/dist/create/iso-base-media/create-iso-base-media.js +38 -19
- package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.js +7 -1
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.js +3 -0
- package/dist/create/media-fn.d.ts +0 -1
- package/dist/create/progress-tracker.d.ts +2 -0
- package/dist/create/progress-tracker.js +32 -8
- package/dist/emit-available-info.js +13 -2
- package/dist/esm/index.mjs +1325 -247
- package/dist/get-container.d.ts +1 -1
- package/dist/get-container.js +3 -0
- package/dist/get-duration.js +4 -1
- package/dist/get-fps.js +8 -2
- package/dist/get-location.d.ts +13 -0
- package/dist/get-location.js +40 -0
- package/dist/get-tracks.d.ts +4 -3
- package/dist/get-tracks.js +9 -2
- package/dist/get-video-codec.d.ts +1 -2
- package/dist/get-video-codec.js +9 -148
- package/dist/has-all-info.js +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/metadata/get-metadata.js +3 -0
- package/dist/options.d.ts +11 -3
- package/dist/parse-media.js +3 -3
- package/dist/parse-result.d.ts +7 -2
- package/dist/parse-video.js +15 -0
- package/dist/register-track.d.ts +5 -5
- package/dist/register-track.js +16 -10
- package/dist/state/can-skip-tracks.js +1 -0
- package/dist/state/has-tracks-section.d.ts +3 -0
- package/dist/state/has-tracks-section.js +5 -0
- package/dist/state/parser-state.d.ts +2 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/webcodec-sample-types.d.ts +9 -2
- package/package.json +3 -3
- package/dist/add-new-matroska-tracks.d.ts +0 -13
- package/dist/add-new-matroska-tracks.js +0 -29
- package/dist/boxes/iso-base-media/meta/keys.d.ts +0 -10
- package/dist/boxes/iso-base-media/meta/keys.js +0 -17
- package/dist/boxes/iso-base-media/meta/list.d.ts +0 -12
- package/dist/boxes/iso-base-media/meta/list.js +0 -33
- package/dist/boxes/riff/strf.d.ts +0 -7
- package/dist/boxes/riff/strf.js +0 -67
- package/dist/create/mp3/create-mp3.d.ts +0 -2
- package/dist/create/mp3/create-mp3.js +0 -49
- package/dist/get-metadata.d.ts +0 -7
- package/dist/get-metadata.js +0 -63
- package/dist/parser-state.d.ts +0 -33
- package/dist/parser-state.js +0 -162
package/dist/esm/index.mjs
CHANGED
|
@@ -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.
|
|
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(
|
|
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
|
|
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:
|
|
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
|
|
2203
|
-
|
|
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 /
|
|
2222
|
-
dts: Math.round(chunk.dts /
|
|
2223
|
-
duration: Math.round((chunk.duration ?? 0) /
|
|
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,
|
|
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
|
-
|
|
3322
|
-
|
|
3323
|
-
if (
|
|
3324
|
-
|
|
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] =
|
|
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
|
|
4810
|
-
const
|
|
4811
|
-
|
|
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
|
|
4955
|
-
primaries: colrAtom.primaries
|
|
4956
|
-
transferCharacteristics: colrAtom.transfer
|
|
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:
|
|
5106
|
-
codecPrivate:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"
|
|
6268
|
-
|
|
6269
|
-
|
|
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"
|
|
6272
|
-
|
|
6273
|
-
|
|
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
|
-
|
|
6279
|
-
|
|
6439
|
+
track,
|
|
6440
|
+
container
|
|
6280
6441
|
}) => {
|
|
6281
|
-
|
|
6442
|
+
options.parserState.registerOnAvcProfileCallback(async (profile) => {
|
|
6282
6443
|
await registerTrack({
|
|
6283
6444
|
options,
|
|
6284
|
-
|
|
6285
|
-
|
|
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
|
|
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
|
-
|
|
8234
|
-
|
|
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
|
-
|
|
8563
|
-
|
|
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(
|
|
8914
|
+
const sps = buffer.slice(0, end === null ? Infinity : end);
|
|
8594
8915
|
return {
|
|
8595
|
-
|
|
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
|
|
8677
|
-
const duration2 = Math.floor(1 / samplesPerSecond
|
|
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
|
|
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
|
|
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
|
|
8709
|
-
const duration2 = 1 / samplesPerSecond
|
|
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
|
-
|
|
9205
|
-
|
|
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
|
-
|
|
9217
|
-
|
|
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) {
|