@remotion/media-parser 4.0.202 → 4.0.205
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/av1-codec-string.d.ts +0 -5
- package/dist/av1-codec-string.js +1 -18
- package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +6 -1
- package/dist/boxes/iso-base-media/ftype.d.ts +9 -0
- package/dist/boxes/iso-base-media/ftype.js +31 -0
- package/dist/boxes/iso-base-media/get-sample-positions-from-track.d.ts +4 -0
- package/dist/boxes/iso-base-media/get-sample-positions-from-track.js +48 -0
- package/dist/boxes/iso-base-media/make-track.js +3 -30
- package/dist/boxes/iso-base-media/mdat/mdat.js +25 -22
- package/dist/boxes/iso-base-media/mdhd.d.ts +2 -0
- package/dist/boxes/iso-base-media/mdhd.js +6 -7
- package/dist/boxes/iso-base-media/mvhd.js +11 -13
- package/dist/boxes/iso-base-media/process-box.js +36 -0
- package/dist/boxes/iso-base-media/tfdt.d.ts +12 -0
- package/dist/boxes/iso-base-media/tfdt.js +20 -0
- package/dist/boxes/iso-base-media/tfhd.d.ts +16 -0
- package/dist/boxes/iso-base-media/tfhd.js +41 -0
- package/dist/boxes/iso-base-media/tkhd.js +9 -12
- package/dist/boxes/iso-base-media/trun.d.ts +21 -0
- package/dist/boxes/iso-base-media/trun.js +44 -0
- package/dist/boxes/webm/bitstream/av1.js +1 -10
- package/dist/boxes/webm/ebml.d.ts +1 -1
- package/dist/boxes/webm/get-track.js +2 -2
- package/dist/boxes/webm/segments/seek-position.js +1 -1
- package/dist/boxes/webm/segments/seek.d.ts +1 -1
- package/dist/boxes/webm/segments/seek.js +8 -2
- package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
- package/dist/boxes/webm/tracks.d.ts +8 -0
- package/dist/boxes/webm/tracks.js +21 -0
- package/dist/buffer-iterator.d.ts +1 -0
- package/dist/buffer-iterator.js +3 -2
- package/dist/create/cluster-segment.d.ts +10 -0
- package/dist/create/cluster-segment.js +41 -0
- package/dist/create/create-media.d.ts +6 -1
- package/dist/create/create-media.js +58 -4
- package/dist/create/matroska-header.d.ts +1 -1
- package/dist/create/matroska-info.d.ts +1 -1
- package/dist/create/matroska-info.js +2 -2
- package/dist/create/matroska-segment.d.ts +2 -1
- package/dist/create/matroska-trackentry.d.ts +5 -4
- package/dist/from-web.js +6 -15
- package/dist/get-duration.d.ts +3 -2
- package/dist/get-duration.js +24 -4
- package/dist/get-tracks.d.ts +4 -4
- package/dist/get-video-metadata.d.ts +2 -0
- package/dist/get-video-metadata.js +44 -0
- package/dist/has-all-info.js +1 -1
- package/dist/parse-media.js +1 -1
- package/dist/parse-result.d.ts +4 -1
- package/dist/read-and-increment-offset.d.ts +28 -0
- package/dist/read-and-increment-offset.js +177 -0
- package/dist/samples-from-moof.d.ts +6 -0
- package/dist/samples-from-moof.js +75 -0
- package/dist/traversal.d.ts +8 -1
- package/dist/traversal.js +39 -1
- package/dist/understand-vorbis.d.ts +1 -0
- package/dist/understand-vorbis.js +12 -0
- package/dist/writers/web-fs.js +21 -5
- package/dist/writers/writer.d.ts +3 -1
- package/package.json +2 -2
- package/src/boxes/iso-base-media/esds/decoder-specific-config.ts +8 -1
- package/src/boxes/iso-base-media/get-sample-positions-from-track.ts +69 -0
- package/src/boxes/iso-base-media/make-track.ts +4 -45
- package/src/boxes/iso-base-media/mdat/mdat.ts +33 -24
- package/src/boxes/iso-base-media/mdhd.ts +10 -7
- package/src/boxes/iso-base-media/mvhd.ts +15 -14
- package/src/boxes/iso-base-media/process-box.ts +42 -0
- package/src/boxes/iso-base-media/tfdt.ts +37 -0
- package/src/boxes/iso-base-media/tfhd.ts +66 -0
- package/src/boxes/iso-base-media/tkhd.ts +11 -13
- package/src/boxes/iso-base-media/trun.ts +74 -0
- package/src/boxes/webm/get-track.ts +2 -2
- package/src/buffer-iterator.ts +3 -2
- package/src/get-duration.ts +40 -5
- package/src/get-tracks.ts +4 -4
- package/src/has-all-info.ts +1 -1
- package/src/parse-media.ts +1 -1
- package/src/parse-result.ts +7 -1
- package/src/samples-from-moof.ts +102 -0
- package/src/test/samples-from-moof.test.ts +2496 -0
- package/src/test/stream-local.test.ts +28 -30
- package/src/test/stream-samples.test.ts +153 -231
- package/src/traversal.ts +56 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/bitstream/av1.d.ts +0 -2
- package/dist/bitstream/av1.js +0 -12
- package/dist/boxes/iso-base-media/avcc-hvcc.d.ts +0 -20
- package/dist/boxes/iso-base-media/avcc-hvcc.js +0 -73
- package/dist/boxes/iso-base-media/avcc.d.ts +0 -18
- package/dist/boxes/iso-base-media/avcc.js +0 -27
- package/dist/boxes/iso-base-media/esds-descriptors.d.ts +0 -21
- package/dist/boxes/iso-base-media/esds-descriptors.js +0 -62
- package/dist/boxes/iso-base-media/esds.d.ts +0 -15
- package/dist/boxes/iso-base-media/esds.js +0 -27
- package/dist/create-media.d.ts +0 -1
- package/dist/create-media.js +0 -78
- package/dist/from-input-type-file.d.ts +0 -2
- package/dist/from-input-type-file.js +0 -37
- package/dist/get-codec.d.ts +0 -4
- package/dist/get-codec.js +0 -22
- package/dist/web-file.d.ts +0 -2
- package/dist/web-file.js +0 -37
- /package/dist/{get-samples.d.ts → boxes/webm/bitstream/av1/frame.d.ts} +0 -0
- /package/dist/{get-samples.js → boxes/webm/bitstream/av1/frame.js} +0 -0
- /package/dist/{sample-aspect-ratio.d.ts → boxes/webm/bitstream/h264/get-h264-descriptor.d.ts} +0 -0
- /package/dist/{sample-aspect-ratio.js → boxes/webm/bitstream/h264/get-h264-descriptor.js} +0 -0
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
import type { ColorParameterBox } from './boxes/iso-base-media/stsd/colr';
|
|
2
2
|
import type { Av1BitstreamHeaderSegment } from './boxes/webm/bitstream/av1/header-segment';
|
|
3
|
-
import type { ClusterSegment, TrackEntrySegment } from './boxes/webm/segments/track-entry';
|
|
4
3
|
export declare const constructAv1CodecString: (av1BitstreamHeader: Av1BitstreamHeaderSegment, colrAtom: ColorParameterBox | null) => string;
|
|
5
|
-
export declare const av1CodecStringToString: ({ track, clusterSegment, }: {
|
|
6
|
-
track: TrackEntrySegment;
|
|
7
|
-
clusterSegment: ClusterSegment;
|
|
8
|
-
}) => string | null;
|
package/dist/av1-codec-string.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// https://aomediacodec.github.io/av1-isobmff/#codecsparam
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
5
|
-
const traversal_1 = require("./boxes/webm/traversal");
|
|
6
|
-
const traversal_2 = require("./traversal");
|
|
4
|
+
exports.constructAv1CodecString = void 0;
|
|
7
5
|
const constructAv1CodecString = (av1BitstreamHeader, colrAtom) => {
|
|
8
6
|
let str = 'av01.';
|
|
9
7
|
// Profile
|
|
@@ -91,18 +89,3 @@ const constructAv1CodecString = (av1BitstreamHeader, colrAtom) => {
|
|
|
91
89
|
return str;
|
|
92
90
|
};
|
|
93
91
|
exports.constructAv1CodecString = constructAv1CodecString;
|
|
94
|
-
const av1CodecStringToString = ({ track, clusterSegment, }) => {
|
|
95
|
-
const codecSegment = (0, traversal_2.getCodecSegment)(track);
|
|
96
|
-
if (!codecSegment) {
|
|
97
|
-
throw new Error('Expected codec segment');
|
|
98
|
-
}
|
|
99
|
-
if (codecSegment.codec !== 'V_AV1') {
|
|
100
|
-
throw new Error(`Should not call this function if it is not AV1: ${codecSegment.codec}`);
|
|
101
|
-
}
|
|
102
|
-
const av1BitstreamHeader = (0, traversal_1.getAv1BitstreamHeader)(clusterSegment);
|
|
103
|
-
if (!av1BitstreamHeader) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
return (0, exports.constructAv1CodecString)(av1BitstreamHeader, null);
|
|
107
|
-
};
|
|
108
|
-
exports.av1CodecStringToString = av1CodecStringToString;
|
|
@@ -27,12 +27,17 @@ const parseDecoderSpecificConfig = (iterator) => {
|
|
|
27
27
|
if (read < layerSize) {
|
|
28
28
|
iterator.discard(layerSize - read);
|
|
29
29
|
}
|
|
30
|
+
// Working around Chrome bug
|
|
31
|
+
// https://issues.chromium.org/issues/360083330#comment5
|
|
32
|
+
const patchedAsBytes = bytes.byteLength === 2 && bytes[0] === 17 && bytes[1] === 136
|
|
33
|
+
? new Uint8Array([17, 144])
|
|
34
|
+
: bytes;
|
|
30
35
|
return {
|
|
31
36
|
type: 'audio-specific-config',
|
|
32
37
|
audioObjectType,
|
|
33
38
|
samplingFrequencyIndex,
|
|
34
39
|
channelConfiguration,
|
|
35
|
-
asBytes:
|
|
40
|
+
asBytes: patchedAsBytes,
|
|
36
41
|
};
|
|
37
42
|
};
|
|
38
43
|
exports.parseDecoderSpecificConfig = parseDecoderSpecificConfig;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BaseBox } from './base-type';
|
|
2
|
+
export interface FtypBox extends BaseBox {
|
|
3
|
+
type: 'ftyp-box';
|
|
4
|
+
majorBrand: string;
|
|
5
|
+
minorVersion: number;
|
|
6
|
+
compatibleBrands: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare const fourByteToNumber: (data: ArrayBuffer, from: number) => number;
|
|
9
|
+
export declare const parseFtyp: (data: ArrayBuffer, offset: number) => FtypBox;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseFtyp = exports.fourByteToNumber = void 0;
|
|
4
|
+
const fourByteToNumber = (data, from) => {
|
|
5
|
+
const view = new DataView(data);
|
|
6
|
+
return ((view.getUint8(from + 0) << 24) |
|
|
7
|
+
(view.getUint8(from + 1) << 16) |
|
|
8
|
+
(view.getUint8(from + 2) << 8) |
|
|
9
|
+
view.getUint8(from + 3));
|
|
10
|
+
};
|
|
11
|
+
exports.fourByteToNumber = fourByteToNumber;
|
|
12
|
+
const parseFtyp = (data, offset) => {
|
|
13
|
+
const majorBrand = new TextDecoder().decode(data.slice(8, 12)).trim();
|
|
14
|
+
const minorVersion = (0, exports.fourByteToNumber)(data, 12);
|
|
15
|
+
const rest = data.slice(16);
|
|
16
|
+
const types = rest.byteLength / 4;
|
|
17
|
+
const compatibleBrands = [];
|
|
18
|
+
for (let i = 0; i < types; i++) {
|
|
19
|
+
const fourBytes = rest.slice(i * 4, i * 4 + 4);
|
|
20
|
+
compatibleBrands.push(new TextDecoder().decode(fourBytes).trim());
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
type: 'ftyp-box',
|
|
24
|
+
majorBrand,
|
|
25
|
+
minorVersion,
|
|
26
|
+
compatibleBrands,
|
|
27
|
+
offset,
|
|
28
|
+
boxSize: data.byteLength,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
exports.parseFtyp = parseFtyp;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SamplePosition } from '../../get-sample-positions';
|
|
2
|
+
import type { IsoBaseMediaBox } from '../../parse-result';
|
|
3
|
+
import type { TrakBox } from './trak/trak';
|
|
4
|
+
export declare const getSamplePositionsFromTrack: (trakBox: TrakBox, moofBox: IsoBaseMediaBox | null) => SamplePosition[];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSamplePositionsFromTrack = void 0;
|
|
4
|
+
const get_fps_1 = require("../../get-fps");
|
|
5
|
+
const get_sample_positions_1 = require("../../get-sample-positions");
|
|
6
|
+
const samples_from_moof_1 = require("../../samples-from-moof");
|
|
7
|
+
const traversal_1 = require("../../traversal");
|
|
8
|
+
const getSamplePositionsFromTrack = (trakBox, moofBox) => {
|
|
9
|
+
const stszBox = (0, traversal_1.getStszBox)(trakBox);
|
|
10
|
+
const stcoBox = (0, traversal_1.getStcoBox)(trakBox);
|
|
11
|
+
const stscBox = (0, traversal_1.getStscBox)(trakBox);
|
|
12
|
+
const stssBox = (0, traversal_1.getStssBox)(trakBox);
|
|
13
|
+
const sttsBox = (0, traversal_1.getSttsBox)(trakBox);
|
|
14
|
+
const tkhdBox = (0, traversal_1.getTkhdBox)(trakBox);
|
|
15
|
+
const cttsBox = (0, traversal_1.getCttsBox)(trakBox);
|
|
16
|
+
const timescaleAndDuration = (0, get_fps_1.getTimescaleAndDuration)(trakBox);
|
|
17
|
+
if (!tkhdBox) {
|
|
18
|
+
throw new Error('Expected tkhd box in trak box');
|
|
19
|
+
}
|
|
20
|
+
if (!stszBox) {
|
|
21
|
+
throw new Error('Expected stsz box in trak box');
|
|
22
|
+
}
|
|
23
|
+
if (!stcoBox) {
|
|
24
|
+
throw new Error('Expected stco box in trak box');
|
|
25
|
+
}
|
|
26
|
+
if (!stscBox) {
|
|
27
|
+
throw new Error('Expected stsc box in trak box');
|
|
28
|
+
}
|
|
29
|
+
if (!sttsBox) {
|
|
30
|
+
throw new Error('Expected stts box in trak box');
|
|
31
|
+
}
|
|
32
|
+
if (!timescaleAndDuration) {
|
|
33
|
+
throw new Error('Expected timescale and duration in trak box');
|
|
34
|
+
}
|
|
35
|
+
let samplePositions = (0, get_sample_positions_1.getSamplePositions)({
|
|
36
|
+
stcoBox,
|
|
37
|
+
stscBox,
|
|
38
|
+
stszBox,
|
|
39
|
+
stssBox,
|
|
40
|
+
sttsBox,
|
|
41
|
+
cttsBox,
|
|
42
|
+
});
|
|
43
|
+
if (samplePositions.length === 0 && moofBox) {
|
|
44
|
+
samplePositions = (0, samples_from_moof_1.getSamplesFromMoof)({ moofBox, trackId: tkhdBox.trackId });
|
|
45
|
+
}
|
|
46
|
+
return samplePositions;
|
|
47
|
+
};
|
|
48
|
+
exports.getSamplePositionsFromTrack = getSamplePositionsFromTrack;
|
|
@@ -4,45 +4,18 @@ exports.makeBaseMediaTrack = void 0;
|
|
|
4
4
|
const get_audio_codec_1 = require("../../get-audio-codec");
|
|
5
5
|
const get_fps_1 = require("../../get-fps");
|
|
6
6
|
const get_sample_aspect_ratio_1 = require("../../get-sample-aspect-ratio");
|
|
7
|
-
const get_sample_positions_1 = require("../../get-sample-positions");
|
|
8
7
|
const get_video_codec_1 = require("../../get-video-codec");
|
|
9
8
|
const traversal_1 = require("../../traversal");
|
|
10
9
|
const makeBaseMediaTrack = (trakBox) => {
|
|
11
|
-
const stszBox = (0, traversal_1.getStszBox)(trakBox);
|
|
12
|
-
const stcoBox = (0, traversal_1.getStcoBox)(trakBox);
|
|
13
|
-
const stscBox = (0, traversal_1.getStscBox)(trakBox);
|
|
14
|
-
const stssBox = (0, traversal_1.getStssBox)(trakBox);
|
|
15
|
-
const sttsBox = (0, traversal_1.getSttsBox)(trakBox);
|
|
16
10
|
const tkhdBox = (0, traversal_1.getTkhdBox)(trakBox);
|
|
17
|
-
const cttsBox = (0, traversal_1.getCttsBox)(trakBox);
|
|
18
11
|
const videoDescriptors = (0, traversal_1.getVideoDescriptors)(trakBox);
|
|
19
12
|
const timescaleAndDuration = (0, get_fps_1.getTimescaleAndDuration)(trakBox);
|
|
20
13
|
if (!tkhdBox) {
|
|
21
14
|
throw new Error('Expected tkhd box in trak box');
|
|
22
15
|
}
|
|
23
|
-
if (!stszBox) {
|
|
24
|
-
throw new Error('Expected stsz box in trak box');
|
|
25
|
-
}
|
|
26
|
-
if (!stcoBox) {
|
|
27
|
-
throw new Error('Expected stco box in trak box');
|
|
28
|
-
}
|
|
29
|
-
if (!stscBox) {
|
|
30
|
-
throw new Error('Expected stsc box in trak box');
|
|
31
|
-
}
|
|
32
|
-
if (!sttsBox) {
|
|
33
|
-
throw new Error('Expected stts box in trak box');
|
|
34
|
-
}
|
|
35
16
|
if (!timescaleAndDuration) {
|
|
36
17
|
throw new Error('Expected timescale and duration in trak box');
|
|
37
18
|
}
|
|
38
|
-
const samplePositions = (0, get_sample_positions_1.getSamplePositions)({
|
|
39
|
-
stcoBox,
|
|
40
|
-
stscBox,
|
|
41
|
-
stszBox,
|
|
42
|
-
stssBox,
|
|
43
|
-
sttsBox,
|
|
44
|
-
cttsBox,
|
|
45
|
-
});
|
|
46
19
|
if ((0, get_fps_1.trakBoxContainsAudio)(trakBox)) {
|
|
47
20
|
const numberOfChannels = (0, get_audio_codec_1.getNumberOfChannelsFromTrak)(trakBox);
|
|
48
21
|
if (numberOfChannels === null) {
|
|
@@ -55,21 +28,21 @@ const makeBaseMediaTrack = (trakBox) => {
|
|
|
55
28
|
const { codecString, description } = (0, get_audio_codec_1.getAudioCodecStringFromTrak)(trakBox);
|
|
56
29
|
return {
|
|
57
30
|
type: 'audio',
|
|
58
|
-
samplePositions,
|
|
59
31
|
trackId: tkhdBox.trackId,
|
|
60
32
|
timescale: timescaleAndDuration.timescale,
|
|
61
33
|
codec: codecString,
|
|
62
34
|
numberOfChannels,
|
|
63
35
|
sampleRate,
|
|
64
36
|
description,
|
|
37
|
+
trakBox,
|
|
65
38
|
};
|
|
66
39
|
}
|
|
67
40
|
if (!(0, get_fps_1.trakBoxContainsVideo)(trakBox)) {
|
|
68
41
|
return {
|
|
69
42
|
type: 'other',
|
|
70
|
-
samplePositions,
|
|
71
43
|
trackId: tkhdBox.trackId,
|
|
72
44
|
timescale: timescaleAndDuration.timescale,
|
|
45
|
+
trakBox,
|
|
73
46
|
};
|
|
74
47
|
}
|
|
75
48
|
const videoSample = (0, get_sample_aspect_ratio_1.getVideoSample)(trakBox);
|
|
@@ -92,7 +65,6 @@ const makeBaseMediaTrack = (trakBox) => {
|
|
|
92
65
|
}
|
|
93
66
|
const track = {
|
|
94
67
|
type: 'video',
|
|
95
|
-
samplePositions,
|
|
96
68
|
trackId: tkhdBox.trackId,
|
|
97
69
|
description: videoDescriptors !== null && videoDescriptors !== void 0 ? videoDescriptors : undefined,
|
|
98
70
|
timescale: timescaleAndDuration.timescale,
|
|
@@ -106,6 +78,7 @@ const makeBaseMediaTrack = (trakBox) => {
|
|
|
106
78
|
displayAspectWidth,
|
|
107
79
|
displayAspectHeight,
|
|
108
80
|
rotation,
|
|
81
|
+
trakBox,
|
|
109
82
|
};
|
|
110
83
|
return track;
|
|
111
84
|
};
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseMdat = void 0;
|
|
4
4
|
const get_tracks_1 = require("../../../get-tracks");
|
|
5
|
+
const traversal_1 = require("../../../traversal");
|
|
6
|
+
const get_sample_positions_from_track_1 = require("../get-sample-positions-from-track");
|
|
5
7
|
const parseMdat = async ({ data, size, fileOffset, existingBoxes, options, }) => {
|
|
6
8
|
const alreadyHas = (0, get_tracks_1.hasTracks)(existingBoxes);
|
|
7
9
|
if (!alreadyHas) {
|
|
@@ -21,12 +23,13 @@ const parseMdat = async ({ data, size, fileOffset, existingBoxes, options, }) =>
|
|
|
21
23
|
];
|
|
22
24
|
const flatSamples = allTracks
|
|
23
25
|
.map((track) => {
|
|
24
|
-
|
|
26
|
+
const samplePositions = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)(track.trakBox, (0, traversal_1.getMoofBox)(existingBoxes));
|
|
27
|
+
if (!samplePositions) {
|
|
25
28
|
throw new Error('No sample positions');
|
|
26
29
|
}
|
|
27
|
-
return
|
|
30
|
+
return samplePositions.map((samplePosition) => {
|
|
28
31
|
return {
|
|
29
|
-
track,
|
|
32
|
+
track: { ...track },
|
|
30
33
|
samplePosition,
|
|
31
34
|
};
|
|
32
35
|
});
|
|
@@ -34,10 +37,10 @@ const parseMdat = async ({ data, size, fileOffset, existingBoxes, options, }) =>
|
|
|
34
37
|
.flat(1);
|
|
35
38
|
// eslint-disable-next-line no-constant-condition
|
|
36
39
|
while (true) {
|
|
37
|
-
const
|
|
40
|
+
const samplesWithIndex = flatSamples.find((sample) => {
|
|
38
41
|
return sample.samplePosition.offset === data.counter.getOffset();
|
|
39
42
|
});
|
|
40
|
-
if (!
|
|
43
|
+
if (!samplesWithIndex) {
|
|
41
44
|
// There are various reasons why in mdat we find weird stuff:
|
|
42
45
|
// - iphonevideo.hevc has a fake hoov atom which is not mapped
|
|
43
46
|
// - corrupted.mp4 has a corrupt table
|
|
@@ -54,31 +57,31 @@ const parseMdat = async ({ data, size, fileOffset, existingBoxes, options, }) =>
|
|
|
54
57
|
break;
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
|
-
if (data.bytesRemaining() <
|
|
60
|
+
if (data.bytesRemaining() < samplesWithIndex.samplePosition.size) {
|
|
58
61
|
break;
|
|
59
62
|
}
|
|
60
|
-
const bytes = data.getSlice(
|
|
61
|
-
if (
|
|
62
|
-
await options.parserState.onAudioSample(
|
|
63
|
+
const bytes = data.getSlice(samplesWithIndex.samplePosition.size);
|
|
64
|
+
if (samplesWithIndex.track.type === 'audio') {
|
|
65
|
+
await options.parserState.onAudioSample(samplesWithIndex.track.trackId, {
|
|
63
66
|
data: bytes,
|
|
64
|
-
timestamp:
|
|
65
|
-
trackId:
|
|
66
|
-
type:
|
|
67
|
+
timestamp: samplesWithIndex.samplePosition.offset,
|
|
68
|
+
trackId: samplesWithIndex.track.trackId,
|
|
69
|
+
type: samplesWithIndex.samplePosition.isKeyframe ? 'key' : 'delta',
|
|
67
70
|
});
|
|
68
71
|
}
|
|
69
|
-
if (
|
|
70
|
-
const timestamp = (
|
|
71
|
-
|
|
72
|
-
const duration = (
|
|
73
|
-
|
|
74
|
-
await options.parserState.onVideoSample(
|
|
72
|
+
if (samplesWithIndex.track.type === 'video') {
|
|
73
|
+
const timestamp = Math.floor((samplesWithIndex.samplePosition.cts * 1000000) /
|
|
74
|
+
samplesWithIndex.track.timescale);
|
|
75
|
+
const duration = Math.floor((samplesWithIndex.samplePosition.duration * 1000000) /
|
|
76
|
+
samplesWithIndex.track.timescale);
|
|
77
|
+
await options.parserState.onVideoSample(samplesWithIndex.track.trackId, {
|
|
75
78
|
data: bytes,
|
|
76
79
|
timestamp,
|
|
77
80
|
duration,
|
|
78
|
-
cts:
|
|
79
|
-
dts:
|
|
80
|
-
trackId:
|
|
81
|
-
type:
|
|
81
|
+
cts: samplesWithIndex.samplePosition.cts,
|
|
82
|
+
dts: samplesWithIndex.samplePosition.dts,
|
|
83
|
+
trackId: samplesWithIndex.track.trackId,
|
|
84
|
+
type: samplesWithIndex.samplePosition.isKeyframe ? 'key' : 'delta',
|
|
82
85
|
});
|
|
83
86
|
}
|
|
84
87
|
const remaining = size - (data.counter.getOffset() - fileOffset);
|
|
@@ -3,17 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseMdhd = void 0;
|
|
4
4
|
const parseMdhd = ({ data, size, fileOffset, }) => {
|
|
5
5
|
const version = data.getUint8();
|
|
6
|
-
if (version !== 0) {
|
|
7
|
-
throw new Error(`Unsupported MDHD version ${version}`);
|
|
8
|
-
}
|
|
9
6
|
// flags, we discard them
|
|
10
7
|
data.discard(3);
|
|
11
8
|
// creation time
|
|
12
|
-
data.
|
|
9
|
+
const creationTime = version === 1 ? Number(data.getUint64()) : data.getUint32();
|
|
13
10
|
// modification time
|
|
14
|
-
data.
|
|
11
|
+
const modificationTime = version === 1 ? Number(data.getUint64()) : data.getUint32();
|
|
15
12
|
const timescale = data.getUint32();
|
|
16
|
-
const duration = data.getUint32();
|
|
13
|
+
const duration = version === 1 ? data.getUint64() : data.getUint32();
|
|
17
14
|
const language = data.getUint16();
|
|
18
15
|
// quality
|
|
19
16
|
const quality = data.getUint16();
|
|
@@ -23,11 +20,13 @@ const parseMdhd = ({ data, size, fileOffset, }) => {
|
|
|
23
20
|
}
|
|
24
21
|
return {
|
|
25
22
|
type: 'mdhd-box',
|
|
26
|
-
duration,
|
|
23
|
+
duration: Number(duration),
|
|
27
24
|
timescale,
|
|
28
25
|
version,
|
|
29
26
|
language,
|
|
30
27
|
quality,
|
|
28
|
+
creationTime,
|
|
29
|
+
modificationTime,
|
|
31
30
|
};
|
|
32
31
|
};
|
|
33
32
|
exports.parseMdhd = parseMdhd;
|
|
@@ -5,19 +5,13 @@ const buffer_iterator_1 = require("../../buffer-iterator");
|
|
|
5
5
|
const to_date_1 = require("./to-date");
|
|
6
6
|
const parseMvhd = ({ iterator, offset, size, }) => {
|
|
7
7
|
const version = iterator.getUint8();
|
|
8
|
-
if (version !== 0) {
|
|
9
|
-
throw new Error(`Unsupported MVHD version ${version}`);
|
|
10
|
-
}
|
|
11
|
-
if (size !== 108) {
|
|
12
|
-
throw new Error(`Expected mvhd size of version 0 to be 108, got ${size}`);
|
|
13
|
-
}
|
|
14
8
|
// Flags, we discard them
|
|
15
9
|
iterator.discard(3);
|
|
16
|
-
const creationTime = iterator.getUint32();
|
|
17
|
-
const modificationTime = iterator.getUint32();
|
|
10
|
+
const creationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
11
|
+
const modificationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
18
12
|
const timeScale = iterator.getUint32();
|
|
19
|
-
const durationInUnits = iterator.getUint32();
|
|
20
|
-
const durationInSeconds = durationInUnits / timeScale;
|
|
13
|
+
const durationInUnits = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
14
|
+
const durationInSeconds = Number(durationInUnits) / timeScale;
|
|
21
15
|
const rateArray = iterator.getSlice(4);
|
|
22
16
|
const rateView = (0, buffer_iterator_1.getArrayBufferIterator)(rateArray, rateArray.length);
|
|
23
17
|
const rate = rateView.getInt8() * 10 +
|
|
@@ -47,11 +41,15 @@ const parseMvhd = ({ iterator, offset, size, }) => {
|
|
|
47
41
|
// next track id
|
|
48
42
|
const nextTrackId = iterator.getUint32();
|
|
49
43
|
volumeView.destroy();
|
|
44
|
+
const bytesRemaining = size - (iterator.counter.getOffset() - offset);
|
|
45
|
+
if (bytesRemaining !== 0) {
|
|
46
|
+
throw new Error('expected 0 bytes ' + bytesRemaining);
|
|
47
|
+
}
|
|
50
48
|
return {
|
|
51
|
-
creationTime: (0, to_date_1.toUnixTimestamp)(creationTime),
|
|
52
|
-
modificationTime: (0, to_date_1.toUnixTimestamp)(modificationTime),
|
|
49
|
+
creationTime: (0, to_date_1.toUnixTimestamp)(Number(creationTime)),
|
|
50
|
+
modificationTime: (0, to_date_1.toUnixTimestamp)(Number(modificationTime)),
|
|
53
51
|
timeScale,
|
|
54
|
-
durationInUnits,
|
|
52
|
+
durationInUnits: Number(durationInUnits),
|
|
55
53
|
durationInSeconds,
|
|
56
54
|
rate,
|
|
57
55
|
volume,
|
|
@@ -23,14 +23,19 @@ const stsd_1 = require("./stsd/stsd");
|
|
|
23
23
|
const stss_1 = require("./stsd/stss");
|
|
24
24
|
const stsz_1 = require("./stsd/stsz");
|
|
25
25
|
const stts_1 = require("./stsd/stts");
|
|
26
|
+
const tfdt_1 = require("./tfdt");
|
|
27
|
+
const tfhd_1 = require("./tfhd");
|
|
26
28
|
const tkhd_1 = require("./tkhd");
|
|
27
29
|
const trak_1 = require("./trak/trak");
|
|
30
|
+
const trun_1 = require("./trun");
|
|
28
31
|
const getChildren = async ({ boxType, iterator, bytesRemainingInBox, options, littleEndian, }) => {
|
|
29
32
|
const parseChildren = boxType === 'mdia' ||
|
|
30
33
|
boxType === 'minf' ||
|
|
31
34
|
boxType === 'stbl' ||
|
|
35
|
+
boxType === 'moof' ||
|
|
32
36
|
boxType === 'dims' ||
|
|
33
37
|
boxType === 'wave' ||
|
|
38
|
+
boxType === 'traf' ||
|
|
34
39
|
boxType === 'stsb';
|
|
35
40
|
if (parseChildren) {
|
|
36
41
|
const parsed = await (0, exports.parseBoxes)({
|
|
@@ -183,6 +188,24 @@ const processBox = async ({ iterator, allowIncompleteBoxes, parsedBoxes, options
|
|
|
183
188
|
skipTo: null,
|
|
184
189
|
};
|
|
185
190
|
}
|
|
191
|
+
if (boxType === 'trun') {
|
|
192
|
+
const box = (0, trun_1.parseTrun)({ iterator, offset: fileOffset, size: boxSize });
|
|
193
|
+
return {
|
|
194
|
+
type: 'complete',
|
|
195
|
+
box,
|
|
196
|
+
size: boxSize,
|
|
197
|
+
skipTo: null,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
if (boxType === 'tfdt') {
|
|
201
|
+
const box = (0, tfdt_1.parseTfdt)({ iterator, size: boxSize, offset: fileOffset });
|
|
202
|
+
return {
|
|
203
|
+
type: 'complete',
|
|
204
|
+
box,
|
|
205
|
+
size: boxSize,
|
|
206
|
+
skipTo: null,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
186
209
|
if (boxType === 'stsd') {
|
|
187
210
|
const box = await (0, stsd_1.parseStsd)({
|
|
188
211
|
iterator,
|
|
@@ -380,6 +403,19 @@ const processBox = async ({ iterator, allowIncompleteBoxes, parsedBoxes, options
|
|
|
380
403
|
skipTo: null,
|
|
381
404
|
};
|
|
382
405
|
}
|
|
406
|
+
if (boxType === 'tfhd') {
|
|
407
|
+
const box = (0, tfhd_1.getTfhd)({
|
|
408
|
+
iterator,
|
|
409
|
+
offset: fileOffset,
|
|
410
|
+
size: boxSize,
|
|
411
|
+
});
|
|
412
|
+
return {
|
|
413
|
+
type: 'complete',
|
|
414
|
+
box,
|
|
415
|
+
size: boxSize,
|
|
416
|
+
skipTo: null,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
383
419
|
if (boxType === 'mdhd') {
|
|
384
420
|
const box = (0, mdhd_1.parseMdhd)({
|
|
385
421
|
data: iterator,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
+
export interface TfdtBox {
|
|
3
|
+
type: 'tfdt-box';
|
|
4
|
+
version: number;
|
|
5
|
+
baseMediaDecodeTime: number;
|
|
6
|
+
offset: number;
|
|
7
|
+
}
|
|
8
|
+
export declare const parseTfdt: ({ iterator, size, offset, }: {
|
|
9
|
+
iterator: BufferIterator;
|
|
10
|
+
size: number;
|
|
11
|
+
offset: number;
|
|
12
|
+
}) => TfdtBox;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTfdt = void 0;
|
|
4
|
+
const parseTfdt = ({ iterator, size, offset, }) => {
|
|
5
|
+
const version = iterator.getUint8();
|
|
6
|
+
iterator.discard(3);
|
|
7
|
+
// Flags, discard them
|
|
8
|
+
const num = version === 0 ? iterator.getUint32() : Number(iterator.getUint64());
|
|
9
|
+
const bytesRemaining = size - (iterator.counter.getOffset() - offset);
|
|
10
|
+
if (bytesRemaining !== 0) {
|
|
11
|
+
throw new Error('expected 0 bytes ' + bytesRemaining);
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
type: 'tfdt-box',
|
|
15
|
+
version,
|
|
16
|
+
baseMediaDecodeTime: num,
|
|
17
|
+
offset,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
exports.parseTfdt = parseTfdt;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
+
export interface TfhdBox {
|
|
3
|
+
type: 'tfhd-box';
|
|
4
|
+
version: number;
|
|
5
|
+
trackId: number;
|
|
6
|
+
baseDataOffset: number;
|
|
7
|
+
baseSampleDescriptionIndex: number;
|
|
8
|
+
defaultSampleDuration: number;
|
|
9
|
+
defaultSampleSize: number;
|
|
10
|
+
defaultSampleFlags: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const getTfhd: ({ iterator, offset, size, }: {
|
|
13
|
+
iterator: BufferIterator;
|
|
14
|
+
size: number;
|
|
15
|
+
offset: number;
|
|
16
|
+
}) => TfhdBox;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTfhd = void 0;
|
|
4
|
+
const getTfhd = ({ iterator, offset, size, }) => {
|
|
5
|
+
const version = iterator.getUint8();
|
|
6
|
+
const flags = iterator.getUint24();
|
|
7
|
+
const trackId = iterator.getUint32();
|
|
8
|
+
const baseDataOffsetPresent = flags & 0x01;
|
|
9
|
+
const baseDataOffset = baseDataOffsetPresent
|
|
10
|
+
? Number(iterator.getUint64())
|
|
11
|
+
: 0;
|
|
12
|
+
const baseSampleDescriptionIndexPresent = flags & 0x02;
|
|
13
|
+
const baseSampleDescriptionIndex = baseSampleDescriptionIndexPresent
|
|
14
|
+
? iterator.getUint32()
|
|
15
|
+
: 0;
|
|
16
|
+
const defaultSampleDurationPresent = flags & 0x08;
|
|
17
|
+
const defaultSampleDuration = defaultSampleDurationPresent
|
|
18
|
+
? iterator.getUint32()
|
|
19
|
+
: 0;
|
|
20
|
+
const defaultSampleSizePresent = flags & 0x10;
|
|
21
|
+
const defaultSampleSize = defaultSampleSizePresent ? iterator.getUint32() : 0;
|
|
22
|
+
const defaultSampleFlagsPresent = flags & 0x20;
|
|
23
|
+
const defaultSampleFlags = defaultSampleFlagsPresent
|
|
24
|
+
? iterator.getUint32()
|
|
25
|
+
: 0;
|
|
26
|
+
const bytesRemaining = size - (iterator.counter.getOffset() - offset);
|
|
27
|
+
if (bytesRemaining !== 0) {
|
|
28
|
+
throw new Error('expected 0 bytes ' + bytesRemaining);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
type: 'tfhd-box',
|
|
32
|
+
version,
|
|
33
|
+
trackId,
|
|
34
|
+
baseDataOffset,
|
|
35
|
+
baseSampleDescriptionIndex,
|
|
36
|
+
defaultSampleDuration,
|
|
37
|
+
defaultSampleSize,
|
|
38
|
+
defaultSampleFlags,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
exports.getTfhd = getTfhd;
|
|
@@ -5,6 +5,9 @@ const to_date_1 = require("./to-date");
|
|
|
5
5
|
function getRotationAngleFromMatrix(matrix) {
|
|
6
6
|
// Extract elements from the matrix
|
|
7
7
|
const [a, b, c, d] = matrix;
|
|
8
|
+
if (a === 0 && b === 0 && c === 0 && d === 0) {
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
8
11
|
// Check if the matrix is a valid rotation matrix
|
|
9
12
|
if (Math.round(a * a + b * b) !== 1 || Math.round(c * c + d * d) !== 1) {
|
|
10
13
|
throw new Error('The provided matrix is not a valid rotation matrix.');
|
|
@@ -23,21 +26,15 @@ const applyRotation = ({ matrix, width, height, }) => {
|
|
|
23
26
|
};
|
|
24
27
|
};
|
|
25
28
|
const parseTkhd = ({ iterator, offset, size, }) => {
|
|
26
|
-
if (size !== 92) {
|
|
27
|
-
throw new Error(`Expected tkhd size of version 0 to be 92, got ${size}`);
|
|
28
|
-
}
|
|
29
29
|
const version = iterator.getUint8();
|
|
30
|
-
if (version !== 0) {
|
|
31
|
-
throw new Error(`Unsupported TKHD version ${version}`);
|
|
32
|
-
}
|
|
33
30
|
// Flags, we discard them
|
|
34
31
|
iterator.discard(3);
|
|
35
|
-
const creationTime = iterator.getUint32();
|
|
36
|
-
const modificationTime = iterator.getUint32();
|
|
32
|
+
const creationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
33
|
+
const modificationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
37
34
|
const trackId = iterator.getUint32();
|
|
38
35
|
// reserved
|
|
39
36
|
iterator.discard(4);
|
|
40
|
-
const duration = iterator.getUint32();
|
|
37
|
+
const duration = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
41
38
|
// reserved 2
|
|
42
39
|
iterator.discard(4);
|
|
43
40
|
// reserved 3
|
|
@@ -71,10 +68,10 @@ const parseTkhd = ({ iterator, offset, size, }) => {
|
|
|
71
68
|
offset,
|
|
72
69
|
boxSize: size,
|
|
73
70
|
type: 'tkhd-box',
|
|
74
|
-
creationTime: (0, to_date_1.toUnixTimestamp)(creationTime),
|
|
75
|
-
modificationTime: (0, to_date_1.toUnixTimestamp)(modificationTime),
|
|
71
|
+
creationTime: (0, to_date_1.toUnixTimestamp)(Number(creationTime)),
|
|
72
|
+
modificationTime: (0, to_date_1.toUnixTimestamp)(Number(modificationTime)),
|
|
76
73
|
trackId,
|
|
77
|
-
duration,
|
|
74
|
+
duration: Number(duration),
|
|
78
75
|
layer,
|
|
79
76
|
alternateGroup,
|
|
80
77
|
volume,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
+
export interface TrunBox {
|
|
3
|
+
type: 'trun-box';
|
|
4
|
+
version: number;
|
|
5
|
+
sampleCount: number;
|
|
6
|
+
dataOffset: number | null;
|
|
7
|
+
firstSampleFlags: number | null;
|
|
8
|
+
samples: TRunSample[];
|
|
9
|
+
}
|
|
10
|
+
type TRunSample = {
|
|
11
|
+
sampleDuration: number | null;
|
|
12
|
+
sampleSize: number | null;
|
|
13
|
+
sampleFlags: number | null;
|
|
14
|
+
sampleCompositionTimeOffset: number | null;
|
|
15
|
+
};
|
|
16
|
+
export declare const parseTrun: ({ iterator, offset, size, }: {
|
|
17
|
+
iterator: BufferIterator;
|
|
18
|
+
offset: number;
|
|
19
|
+
size: number;
|
|
20
|
+
}) => TrunBox;
|
|
21
|
+
export {};
|