@remotion/media-parser 4.0.249 → 4.0.250
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/boxes/iso-base-media/continue-mdat-routine.d.ts +14 -0
- package/dist/boxes/iso-base-media/continue-mdat-routine.js +74 -0
- package/dist/boxes/iso-base-media/get-children.d.ts +2 -8
- package/dist/boxes/iso-base-media/get-children.js +14 -30
- package/dist/boxes/iso-base-media/mdat/mdat.d.ts +3 -23
- package/dist/boxes/iso-base-media/mdat/mdat.js +80 -130
- package/dist/boxes/iso-base-media/moov/moov.d.ts +1 -6
- package/dist/boxes/iso-base-media/moov/moov.js +5 -14
- package/dist/boxes/iso-base-media/parse-all-children.d.ts +8 -0
- package/dist/boxes/iso-base-media/parse-all-children.js +20 -0
- package/dist/boxes/iso-base-media/parse-boxes.d.ts +2 -10
- package/dist/boxes/iso-base-media/parse-boxes.js +33 -116
- package/dist/boxes/iso-base-media/parse-mdat-partially.d.ts +1 -4
- package/dist/boxes/iso-base-media/parse-mdat-partially.js +2 -11
- package/dist/boxes/iso-base-media/process-box.d.ts +1 -9
- package/dist/boxes/iso-base-media/process-box.js +49 -143
- package/dist/boxes/iso-base-media/stsd/mebx.d.ts +1 -4
- package/dist/boxes/iso-base-media/stsd/mebx.js +5 -14
- package/dist/boxes/iso-base-media/stsd/samples.d.ts +4 -12
- package/dist/boxes/iso-base-media/stsd/samples.js +24 -66
- package/dist/boxes/iso-base-media/stsd/stsd.d.ts +1 -4
- package/dist/boxes/iso-base-media/stsd/stsd.js +2 -5
- package/dist/boxes/iso-base-media/trak/trak.d.ts +1 -6
- package/dist/boxes/iso-base-media/trak/trak.js +5 -14
- package/dist/boxes/iso-base-media/traversal.d.ts +0 -2
- package/dist/boxes/iso-base-media/traversal.js +1 -12
- package/dist/boxes/mp3/id3.d.ts +1 -3
- package/dist/boxes/mp3/id3.js +7 -5
- package/dist/boxes/mp3/parse-mp3.d.ts +2 -3
- package/dist/boxes/mp3/parse-mp3.js +3 -19
- package/dist/boxes/riff/expect-riff-box.d.ts +1 -9
- package/dist/boxes/riff/expect-riff-box.js +47 -25
- package/dist/boxes/riff/get-tracks-from-avi.d.ts +1 -1
- package/dist/boxes/riff/get-tracks-from-avi.js +6 -10
- package/dist/boxes/riff/parse-fmt-box.d.ts +3 -2
- package/dist/boxes/riff/parse-fmt-box.js +7 -5
- package/dist/boxes/riff/parse-list-box.d.ts +1 -3
- package/dist/boxes/riff/parse-list-box.js +16 -16
- package/dist/boxes/riff/parse-movi.d.ts +2 -5
- package/dist/boxes/riff/parse-movi.js +34 -56
- package/dist/boxes/riff/parse-riff-body.d.ts +2 -6
- package/dist/boxes/riff/parse-riff-body.js +15 -95
- package/dist/boxes/riff/parse-riff-box.d.ts +1 -4
- package/dist/boxes/riff/parse-riff-box.js +3 -7
- package/dist/boxes/riff/parse-riff-header.d.ts +7 -0
- package/dist/boxes/riff/parse-riff-header.js +23 -0
- package/dist/boxes/riff/parse-riff.d.ts +7 -0
- package/dist/boxes/riff/parse-riff.js +15 -0
- package/dist/boxes/riff/parse-strf.d.ts +4 -4
- package/dist/boxes/riff/parse-strf.js +4 -8
- package/dist/boxes/riff/parse-strh.js +11 -0
- package/dist/boxes/riff/parse-video-section.d.ts +6 -0
- package/dist/boxes/riff/parse-video-section.js +20 -0
- package/dist/boxes/riff/riff-box.d.ts +4 -5
- package/dist/boxes/riff/traversal.d.ts +1 -2
- package/dist/boxes/riff/traversal.js +1 -6
- package/dist/boxes/transport-stream/get-tracks.d.ts +2 -3
- package/dist/boxes/transport-stream/get-tracks.js +4 -3
- package/dist/boxes/transport-stream/parse-packet.d.ts +1 -7
- package/dist/boxes/transport-stream/parse-packet.js +3 -4
- package/dist/boxes/transport-stream/parse-stream-packet.d.ts +1 -5
- package/dist/boxes/transport-stream/parse-stream-packet.js +10 -12
- package/dist/boxes/transport-stream/parse-transport-stream.d.ts +1 -7
- package/dist/boxes/transport-stream/parse-transport-stream.js +7 -26
- package/dist/boxes/transport-stream/process-stream-buffers.d.ts +1 -2
- package/dist/boxes/transport-stream/process-stream-buffers.js +3 -3
- package/dist/boxes/webm/parse-ebml.js +3 -0
- package/dist/boxes/webm/parse-webm-header.d.ts +2 -4
- package/dist/boxes/webm/parse-webm-header.js +41 -25
- package/dist/boxes/webm/segments/parse-children.d.ts +2 -16
- package/dist/boxes/webm/segments/parse-children.js +7 -130
- package/dist/boxes/webm/segments.d.ts +4 -8
- package/dist/boxes/webm/segments.js +41 -123
- package/dist/buffer-iterator.d.ts +0 -3
- package/dist/buffer-iterator.js +6 -16
- package/dist/bun-reader.d.ts +1 -0
- package/dist/bun-reader.js +17 -0
- package/dist/emit-available-info.js +4 -4
- package/dist/esm/from-node.mjs +8 -9
- package/dist/esm/index.mjs +4224 -4950
- package/dist/file-types/detect-file-type.js +4 -2
- package/dist/get-audio-codec.d.ts +1 -1
- package/dist/get-audio-codec.js +2 -2
- package/dist/get-dimensions.js +1 -1
- package/dist/get-duration.js +1 -1
- package/dist/get-is-hdr.d.ts +1 -1
- package/dist/get-is-hdr.js +2 -2
- package/dist/get-tracks.d.ts +1 -1
- package/dist/get-tracks.js +14 -13
- package/dist/get-video-codec.d.ts +1 -1
- package/dist/get-video-codec.js +2 -2
- package/dist/index.d.ts +50 -24
- package/dist/index.js +1 -1
- package/dist/may-skip-video-data/may-skip-video-data.js +6 -2
- package/dist/parse-media.js +45 -30
- package/dist/parse-result.d.ts +1 -18
- package/dist/parse-video.d.ts +3 -17
- package/dist/parse-video.js +45 -32
- package/dist/readers/from-node.js +7 -8
- package/dist/state/can-skip-tracks.d.ts +8 -1
- package/dist/state/can-skip-tracks.js +38 -27
- package/dist/state/iso-base-media/cached-sample-positions.d.ts +15 -0
- package/dist/state/iso-base-media/cached-sample-positions.js +42 -0
- package/dist/state/iso-base-media/iso-state.d.ts +8 -0
- package/dist/state/iso-base-media/iso-state.js +15 -0
- package/dist/state/iso-state.d.ts +4 -0
- package/dist/state/iso-state.js +13 -0
- package/dist/state/parser-state.d.ts +49 -14
- package/dist/state/parser-state.js +11 -3
- package/dist/state/sample-callbacks.d.ts +5 -1
- package/dist/state/sample-callbacks.js +4 -1
- package/dist/state/transport-stream.d.ts +8 -0
- package/dist/state/transport-stream.js +11 -0
- package/dist/state/video-section.d.ts +16 -0
- package/dist/state/video-section.js +37 -0
- package/dist/state/webm.d.ts +15 -0
- package/dist/state/webm.js +32 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/test.json +663 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
+
import type { LogLevel } from '../../log';
|
|
3
|
+
import type { Options, ParseMediaFields } from '../../options';
|
|
4
|
+
import type { IsoBaseMediaBox, ParseResult } from '../../parse-result';
|
|
5
|
+
import type { ParserState } from '../../state/parser-state';
|
|
6
|
+
export declare const continueMdatRoutine: ({ iterator, maxBytes, initialBoxes, state, signal, logLevel, fields, }: {
|
|
7
|
+
iterator: BufferIterator;
|
|
8
|
+
maxBytes: number;
|
|
9
|
+
initialBoxes: IsoBaseMediaBox[];
|
|
10
|
+
state: ParserState;
|
|
11
|
+
signal: AbortSignal | null;
|
|
12
|
+
logLevel: LogLevel;
|
|
13
|
+
fields: Options<ParseMediaFields>;
|
|
14
|
+
}) => Promise<ParseResult>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.continueMdatRoutine = void 0;
|
|
4
|
+
const has_all_info_1 = require("../../has-all-info");
|
|
5
|
+
const may_skip_video_data_1 = require("../../may-skip-video-data/may-skip-video-data");
|
|
6
|
+
const parse_boxes_1 = require("./parse-boxes");
|
|
7
|
+
const traversal_1 = require("./traversal");
|
|
8
|
+
const continueMdatRoutine = async ({ iterator, maxBytes, initialBoxes, state, signal, logLevel, fields, }) => {
|
|
9
|
+
var _a;
|
|
10
|
+
const continueParsing = () => {
|
|
11
|
+
return (0, parse_boxes_1.parseIsoBaseMedia)({
|
|
12
|
+
iterator,
|
|
13
|
+
maxBytes,
|
|
14
|
+
initialBoxes,
|
|
15
|
+
state,
|
|
16
|
+
signal,
|
|
17
|
+
logLevel,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const result = await parseMdatPartially({
|
|
21
|
+
iterator,
|
|
22
|
+
boxSize: continueMdat.boxSize,
|
|
23
|
+
fileOffset: continueMdat.fileOffset,
|
|
24
|
+
parsedBoxes: initialBoxes,
|
|
25
|
+
state,
|
|
26
|
+
signal,
|
|
27
|
+
});
|
|
28
|
+
if (result.type === 'incomplete') {
|
|
29
|
+
throw new Error('Incomplete boxes are not allowed in this routine');
|
|
30
|
+
}
|
|
31
|
+
if (result.type === 'partial-mdat-box') {
|
|
32
|
+
return {
|
|
33
|
+
status: 'incomplete',
|
|
34
|
+
continueParsing,
|
|
35
|
+
skipTo: null,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const alreadyHasMdat = (_a = state.structure
|
|
39
|
+
.getStructureOrNull()) === null || _a === void 0 ? void 0 : _a.boxes.find((b) => b.type === 'mdat-box');
|
|
40
|
+
if (result.box.type === 'mdat-box' && alreadyHasMdat) {
|
|
41
|
+
initialBoxes = initialBoxes.filter((b) => b.type !== 'mdat-box');
|
|
42
|
+
initialBoxes.push(result.box);
|
|
43
|
+
iterator.allowDiscard();
|
|
44
|
+
return {
|
|
45
|
+
continueParsing,
|
|
46
|
+
skipTo: null,
|
|
47
|
+
status: 'incomplete',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
initialBoxes.push(result.box);
|
|
51
|
+
if ((0, has_all_info_1.hasAllInfo)({ fields, state })) {
|
|
52
|
+
return {
|
|
53
|
+
status: 'done',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
iterator.removeBytesRead();
|
|
57
|
+
const mdatState = (0, traversal_1.getMdatBox)(initialBoxes);
|
|
58
|
+
const skipped = (mdatState === null || mdatState === void 0 ? void 0 : mdatState.status) === 'samples-skipped' &&
|
|
59
|
+
!(0, may_skip_video_data_1.maySkipVideoData)({ state }) &&
|
|
60
|
+
state.supportsContentRange;
|
|
61
|
+
if (skipped) {
|
|
62
|
+
return {
|
|
63
|
+
status: 'incomplete',
|
|
64
|
+
continueParsing,
|
|
65
|
+
skipTo: mdatState.fileOffset,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
status: 'incomplete',
|
|
70
|
+
continueParsing,
|
|
71
|
+
skipTo: null,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
exports.continueMdatRoutine = continueMdatRoutine;
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
-
import type { LogLevel } from '../../log';
|
|
3
|
-
import type { Options, ParseMediaFields } from '../../options';
|
|
4
2
|
import type { IsoBaseMediaBox } from '../../parse-result';
|
|
5
3
|
import type { ParserState } from '../../state/parser-state';
|
|
6
|
-
export declare const
|
|
7
|
-
boxType: string;
|
|
4
|
+
export declare const getIsoBaseMediaChildren: ({ iterator, state, size, }: {
|
|
8
5
|
iterator: BufferIterator;
|
|
9
|
-
bytesRemainingInBox: number;
|
|
10
6
|
state: ParserState;
|
|
11
|
-
|
|
12
|
-
logLevel: LogLevel;
|
|
13
|
-
fields: Options<ParseMediaFields>;
|
|
7
|
+
size: number;
|
|
14
8
|
}) => Promise<IsoBaseMediaBox[]>;
|
|
@@ -1,39 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
boxType === 'moof' ||
|
|
11
|
-
boxType === 'dims' ||
|
|
12
|
-
boxType === 'meta' ||
|
|
13
|
-
boxType === 'wave' ||
|
|
14
|
-
boxType === 'traf' ||
|
|
15
|
-
boxType === 'stsb';
|
|
16
|
-
if (parseChildren) {
|
|
17
|
-
const boxes = [];
|
|
18
|
-
const parsed = await (0, parse_boxes_1.parseIsoBaseMediaBoxes)({
|
|
3
|
+
exports.getIsoBaseMediaChildren = void 0;
|
|
4
|
+
const process_box_1 = require("./process-box");
|
|
5
|
+
const getIsoBaseMediaChildren = async ({ iterator, state, size, }) => {
|
|
6
|
+
const boxes = [];
|
|
7
|
+
const initial = iterator.counter.getOffset();
|
|
8
|
+
while (iterator.counter.getOffset() < size + initial) {
|
|
9
|
+
const parsed = await (0, process_box_1.processBox)({
|
|
19
10
|
iterator,
|
|
20
|
-
maxBytes: bytesRemainingInBox,
|
|
21
|
-
allowIncompleteBoxes: false,
|
|
22
|
-
initialBoxes: boxes,
|
|
23
11
|
state,
|
|
24
|
-
signal,
|
|
25
|
-
logLevel,
|
|
26
|
-
fields,
|
|
27
12
|
});
|
|
28
|
-
if (parsed.
|
|
29
|
-
throw new Error('
|
|
13
|
+
if (!parsed.box) {
|
|
14
|
+
throw new Error('Expected box');
|
|
30
15
|
}
|
|
31
|
-
|
|
16
|
+
boxes.push(parsed.box);
|
|
32
17
|
}
|
|
33
|
-
if (
|
|
34
|
-
throw new Error(
|
|
18
|
+
if (iterator.counter.getOffset() > size + initial) {
|
|
19
|
+
throw new Error(`read too many bytes - size: ${size}, read: ${iterator.counter.getOffset() - initial}. initial offset: ${initial}`);
|
|
35
20
|
}
|
|
36
|
-
|
|
37
|
-
return [];
|
|
21
|
+
return boxes;
|
|
38
22
|
};
|
|
39
|
-
exports.
|
|
23
|
+
exports.getIsoBaseMediaChildren = getIsoBaseMediaChildren;
|
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../../buffer-iterator';
|
|
2
|
-
import type { IsoBaseMediaBox } from '../../../parse-result';
|
|
3
|
-
import type { PartialMdatBox } from '../../../parse-video';
|
|
4
2
|
import type { ParserState } from '../../../state/parser-state';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} | {
|
|
8
|
-
status: 'samples-skipped';
|
|
9
|
-
} | {
|
|
10
|
-
status: 'samples-processed';
|
|
11
|
-
};
|
|
12
|
-
export type MdatBox = {
|
|
13
|
-
type: 'mdat-box';
|
|
14
|
-
boxSize: number;
|
|
15
|
-
fileOffset: number;
|
|
16
|
-
} & MdatStatus;
|
|
17
|
-
export declare const parseMdat: ({ data, size, fileOffset, existingBoxes, state, signal, maySkipSampleProcessing, }: {
|
|
18
|
-
data: BufferIterator;
|
|
19
|
-
size: number;
|
|
20
|
-
fileOffset: number;
|
|
21
|
-
existingBoxes: IsoBaseMediaBox[];
|
|
3
|
+
export declare const parseMdatSection: ({ iterator, state, }: {
|
|
4
|
+
iterator: BufferIterator;
|
|
22
5
|
state: ParserState;
|
|
23
|
-
|
|
24
|
-
maySkipSampleProcessing: boolean;
|
|
25
|
-
}) => Promise<MdatBox | PartialMdatBox>;
|
|
26
|
-
export {};
|
|
6
|
+
}) => Promise<number | null>;
|
|
@@ -1,141 +1,91 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.parseMdatSection = void 0;
|
|
4
4
|
const convert_audio_or_video_sample_1 = require("../../../convert-audio-or-video-sample");
|
|
5
5
|
const get_tracks_1 = require("../../../get-tracks");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
const may_skip_video_data_1 = require("../../../may-skip-video-data/may-skip-video-data");
|
|
7
|
+
const cached_sample_positions_1 = require("../../../state/iso-base-media/cached-sample-positions");
|
|
8
|
+
const parseMdatSection = async ({ iterator, state, }) => {
|
|
9
|
+
const videoSection = state.videoSection.getVideoSection();
|
|
10
|
+
// don't need mdat at all, can skip
|
|
11
|
+
if ((0, may_skip_video_data_1.maySkipVideoData)({ state })) {
|
|
12
|
+
return videoSection.size + videoSection.start;
|
|
13
|
+
}
|
|
14
|
+
const alreadyHas = (0, get_tracks_1.getHasTracks)(state.structure.getStructure(), state);
|
|
13
15
|
if (!alreadyHas) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
boxSize: size,
|
|
19
|
-
status: 'samples-skipped',
|
|
20
|
-
fileOffset,
|
|
21
|
-
});
|
|
16
|
+
// Will first read the end and then return
|
|
17
|
+
if (state.supportsContentRange) {
|
|
18
|
+
state.iso.setShouldReturnToVideoSectionAfterEnd(true);
|
|
19
|
+
return videoSection.size + videoSection.start;
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
data.disallowDiscard();
|
|
25
|
-
return Promise.resolve({
|
|
26
|
-
type: 'mdat-box',
|
|
27
|
-
boxSize: size,
|
|
28
|
-
status: 'samples-buffered',
|
|
29
|
-
fileOffset,
|
|
30
|
-
});
|
|
21
|
+
throw new Error('Source does not support reading partially, but metadata is at the end of the file. This would require buffering the entire file in memory, leading to a leak. Remotion does not currently support this scenario, make sure to pass a source that supports Content-Range.');
|
|
31
22
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
50
|
-
})
|
|
51
|
-
.flat(1);
|
|
52
|
-
while (true) {
|
|
53
|
-
if (signal && signal.aborted) {
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
const samplesWithIndex = flatSamples.find((sample) => {
|
|
57
|
-
return sample.samplePosition.offset === data.counter.getOffset();
|
|
58
|
-
});
|
|
59
|
-
if (!samplesWithIndex) {
|
|
60
|
-
// There are various reasons why in mdat we find weird stuff:
|
|
61
|
-
// - iphonevideo.hevc has a fake hoov atom which is not mapped
|
|
62
|
-
// - corrupted.mp4 has a corrupt table
|
|
63
|
-
const nextSample_ = flatSamples
|
|
64
|
-
.filter((s) => s.samplePosition.offset > data.counter.getOffset())
|
|
65
|
-
.sort((a, b) => a.samplePosition.offset - b.samplePosition.offset)[0];
|
|
66
|
-
if (nextSample_) {
|
|
67
|
-
data.discard(nextSample_.samplePosition.offset - data.counter.getOffset());
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
const bytesRemaining = size + fileOffset - data.counter.getOffset();
|
|
72
|
-
data.discard(bytesRemaining);
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (data.bytesRemaining() < samplesWithIndex.samplePosition.size) {
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
const bytes = data.getSlice(samplesWithIndex.samplePosition.size);
|
|
80
|
-
const { cts, dts, duration, isKeyframe, offset } = samplesWithIndex.samplePosition;
|
|
81
|
-
if (samplesWithIndex.track.type === 'audio') {
|
|
82
|
-
await state.callbacks.onAudioSample(samplesWithIndex.track.trackId, (0, convert_audio_or_video_sample_1.convertAudioOrVideoSampleToWebCodecsTimestamps)({
|
|
83
|
-
data: bytes,
|
|
84
|
-
timestamp: cts,
|
|
85
|
-
duration,
|
|
86
|
-
cts,
|
|
87
|
-
dts,
|
|
88
|
-
trackId: samplesWithIndex.track.trackId,
|
|
89
|
-
type: isKeyframe ? 'key' : 'delta',
|
|
90
|
-
offset,
|
|
91
|
-
timescale: samplesWithIndex.track.timescale,
|
|
92
|
-
}, samplesWithIndex.track.timescale));
|
|
93
|
-
}
|
|
94
|
-
if (samplesWithIndex.track.type === 'video') {
|
|
95
|
-
// https://remotion-assets.s3.eu-central-1.amazonaws.com/example-videos/sei_checkpoint.mp4
|
|
96
|
-
// Position in file 0x0001aba615
|
|
97
|
-
// https://github.com/remotion-dev/remotion/issues/4680
|
|
98
|
-
// In Chrome, we may not treat recovery points as keyframes
|
|
99
|
-
// otherwise "a keyframe is required after flushing"
|
|
100
|
-
const nalUnitType = bytes[4] & 0b00011111;
|
|
101
|
-
let isRecoveryPoint = false;
|
|
102
|
-
// SEI (Supplemental enhancement information)
|
|
103
|
-
if (nalUnitType === 6) {
|
|
104
|
-
const seiType = bytes[5];
|
|
105
|
-
isRecoveryPoint = seiType === 6;
|
|
106
|
-
}
|
|
107
|
-
await state.callbacks.onVideoSample(samplesWithIndex.track.trackId, (0, convert_audio_or_video_sample_1.convertAudioOrVideoSampleToWebCodecsTimestamps)({
|
|
108
|
-
data: bytes,
|
|
109
|
-
timestamp: cts,
|
|
110
|
-
duration,
|
|
111
|
-
cts,
|
|
112
|
-
dts,
|
|
113
|
-
trackId: samplesWithIndex.track.trackId,
|
|
114
|
-
type: isKeyframe && !isRecoveryPoint ? 'key' : 'delta',
|
|
115
|
-
offset,
|
|
116
|
-
timescale: samplesWithIndex.track.timescale,
|
|
117
|
-
}, samplesWithIndex.track.timescale));
|
|
118
|
-
}
|
|
119
|
-
const remaining = size - (data.counter.getOffset() - fileOffset);
|
|
120
|
-
data.removeBytesRead();
|
|
121
|
-
if (remaining === 0) {
|
|
122
|
-
break;
|
|
23
|
+
if (!state.iso.flatSamples.getSamples()) {
|
|
24
|
+
state.iso.flatSamples.setSamples((0, cached_sample_positions_1.calculateFlatSamples)(state));
|
|
25
|
+
}
|
|
26
|
+
const flatSamples = state.iso.flatSamples.getSamples();
|
|
27
|
+
const samplesWithIndex = flatSamples.find((sample) => {
|
|
28
|
+
return sample.samplePosition.offset === iterator.counter.getOffset();
|
|
29
|
+
});
|
|
30
|
+
if (!samplesWithIndex) {
|
|
31
|
+
// There are various reasons why in mdat we find weird stuff:
|
|
32
|
+
// - iphonevideo.hevc has a fake hoov atom which is not mapped
|
|
33
|
+
// - corrupted.mp4 has a corrupt table
|
|
34
|
+
const nextSample_ = flatSamples
|
|
35
|
+
.filter((s) => s.samplePosition.offset > iterator.counter.getOffset())
|
|
36
|
+
.sort((a, b) => a.samplePosition.offset - b.samplePosition.offset)[0];
|
|
37
|
+
if (nextSample_) {
|
|
38
|
+
iterator.discard(nextSample_.samplePosition.offset - iterator.counter.getOffset());
|
|
39
|
+
return null;
|
|
123
40
|
}
|
|
41
|
+
// guess we reached the end!
|
|
42
|
+
// iphonevideo.mov has extra padding here, so let's make sure to jump ahead
|
|
43
|
+
return videoSection.size + videoSection.start;
|
|
124
44
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (expectedOffsetNow !== actualOffsetNow) {
|
|
128
|
-
return Promise.resolve({
|
|
129
|
-
type: 'partial-mdat-box',
|
|
130
|
-
boxSize: size,
|
|
131
|
-
fileOffset,
|
|
132
|
-
});
|
|
45
|
+
if (iterator.bytesRemaining() < samplesWithIndex.samplePosition.size) {
|
|
46
|
+
return null;
|
|
133
47
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
48
|
+
const bytes = iterator.getSlice(samplesWithIndex.samplePosition.size);
|
|
49
|
+
const { cts, dts, duration, isKeyframe, offset } = samplesWithIndex.samplePosition;
|
|
50
|
+
if (samplesWithIndex.track.type === 'audio') {
|
|
51
|
+
await state.callbacks.onAudioSample(samplesWithIndex.track.trackId, (0, convert_audio_or_video_sample_1.convertAudioOrVideoSampleToWebCodecsTimestamps)({
|
|
52
|
+
data: bytes,
|
|
53
|
+
timestamp: cts,
|
|
54
|
+
duration,
|
|
55
|
+
cts,
|
|
56
|
+
dts,
|
|
57
|
+
trackId: samplesWithIndex.track.trackId,
|
|
58
|
+
type: isKeyframe ? 'key' : 'delta',
|
|
59
|
+
offset,
|
|
60
|
+
timescale: samplesWithIndex.track.timescale,
|
|
61
|
+
}, samplesWithIndex.track.timescale));
|
|
62
|
+
}
|
|
63
|
+
if (samplesWithIndex.track.type === 'video') {
|
|
64
|
+
// https://remotion-assets.s3.eu-central-1.amazonaws.com/example-videos/sei_checkpoint.mp4
|
|
65
|
+
// Position in file 0x0001aba615
|
|
66
|
+
// https://github.com/remotion-dev/remotion/issues/4680
|
|
67
|
+
// In Chrome, we may not treat recovery points as keyframes
|
|
68
|
+
// otherwise "a keyframe is required after flushing"
|
|
69
|
+
const nalUnitType = bytes[4] & 0b00011111;
|
|
70
|
+
let isRecoveryPoint = false;
|
|
71
|
+
// SEI (Supplemental enhancement information)
|
|
72
|
+
if (nalUnitType === 6) {
|
|
73
|
+
const seiType = bytes[5];
|
|
74
|
+
isRecoveryPoint = seiType === 6;
|
|
75
|
+
}
|
|
76
|
+
await state.callbacks.onVideoSample(samplesWithIndex.track.trackId, (0, convert_audio_or_video_sample_1.convertAudioOrVideoSampleToWebCodecsTimestamps)({
|
|
77
|
+
data: bytes,
|
|
78
|
+
timestamp: cts,
|
|
79
|
+
duration,
|
|
80
|
+
cts,
|
|
81
|
+
dts,
|
|
82
|
+
trackId: samplesWithIndex.track.trackId,
|
|
83
|
+
type: isKeyframe && !isRecoveryPoint ? 'key' : 'delta',
|
|
84
|
+
offset,
|
|
85
|
+
timescale: samplesWithIndex.track.timescale,
|
|
86
|
+
}, samplesWithIndex.track.timescale));
|
|
87
|
+
}
|
|
88
|
+
iterator.removeBytesRead();
|
|
89
|
+
return null;
|
|
140
90
|
};
|
|
141
|
-
exports.
|
|
91
|
+
exports.parseMdatSection = parseMdatSection;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../../buffer-iterator';
|
|
2
|
-
import type { LogLevel } from '../../../log';
|
|
3
|
-
import type { Options, ParseMediaFields } from '../../../options';
|
|
4
2
|
import type { AnySegment } from '../../../parse-result';
|
|
5
3
|
import type { ParserState } from '../../../state/parser-state';
|
|
6
4
|
import type { BaseBox } from '../base-type';
|
|
@@ -8,12 +6,9 @@ export interface MoovBox extends BaseBox {
|
|
|
8
6
|
type: 'moov-box';
|
|
9
7
|
children: AnySegment[];
|
|
10
8
|
}
|
|
11
|
-
export declare const parseMoov: ({ iterator, offset, size, state,
|
|
9
|
+
export declare const parseMoov: ({ iterator, offset, size, state, }: {
|
|
12
10
|
iterator: BufferIterator;
|
|
13
11
|
offset: number;
|
|
14
12
|
size: number;
|
|
15
13
|
state: ParserState;
|
|
16
|
-
signal: AbortSignal | null;
|
|
17
|
-
logLevel: LogLevel;
|
|
18
|
-
fields: Options<ParseMediaFields>;
|
|
19
14
|
}) => Promise<MoovBox>;
|
|
@@ -1,27 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseMoov = void 0;
|
|
4
|
-
const
|
|
5
|
-
const parseMoov = async ({ iterator, offset, size, state,
|
|
6
|
-
const
|
|
7
|
-
const children = await (0, parse_boxes_1.parseIsoBaseMediaBoxes)({
|
|
4
|
+
const get_children_1 = require("../get-children");
|
|
5
|
+
const parseMoov = async ({ iterator, offset, size, state, }) => {
|
|
6
|
+
const children = await (0, get_children_1.getIsoBaseMediaChildren)({
|
|
8
7
|
iterator,
|
|
9
|
-
maxBytes: size - (iterator.counter.getOffset() - offset),
|
|
10
|
-
allowIncompleteBoxes: false,
|
|
11
|
-
initialBoxes: boxes,
|
|
12
8
|
state,
|
|
13
|
-
|
|
14
|
-
logLevel,
|
|
15
|
-
fields,
|
|
9
|
+
size: size - 8,
|
|
16
10
|
});
|
|
17
|
-
if (children.status === 'incomplete') {
|
|
18
|
-
throw new Error('Incomplete boxes are not allowed');
|
|
19
|
-
}
|
|
20
11
|
return {
|
|
21
12
|
offset,
|
|
22
13
|
boxSize: size,
|
|
23
14
|
type: 'moov-box',
|
|
24
|
-
children
|
|
15
|
+
children,
|
|
25
16
|
};
|
|
26
17
|
};
|
|
27
18
|
exports.parseMoov = parseMoov;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
+
import type { LogLevel } from '../../log';
|
|
3
|
+
import type { IsoBaseMediaBox } from '../../parse-result';
|
|
4
|
+
export declare const parseAllChildren: ({ iterator, logLevel, maxOffset, }: {
|
|
5
|
+
iterator: BufferIterator;
|
|
6
|
+
maxOffset: number;
|
|
7
|
+
logLevel: LogLevel;
|
|
8
|
+
}) => Promise<IsoBaseMediaBox[]>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseAllChildren = void 0;
|
|
4
|
+
const process_box_1 = require("./process-box");
|
|
5
|
+
const parseAllChildren = async ({ iterator, logLevel, maxOffset, }) => {
|
|
6
|
+
const boxes = [];
|
|
7
|
+
// TODO: Ensure we are able to parse all children
|
|
8
|
+
while (iterator.counter.getOffset() < maxOffset) {
|
|
9
|
+
const box = await (0, process_box_1.processBox)({
|
|
10
|
+
iterator,
|
|
11
|
+
logLevel,
|
|
12
|
+
parsedBoxes,
|
|
13
|
+
signal,
|
|
14
|
+
state,
|
|
15
|
+
});
|
|
16
|
+
boxes.push(box);
|
|
17
|
+
}
|
|
18
|
+
return boxes;
|
|
19
|
+
};
|
|
20
|
+
exports.parseAllChildren = parseAllChildren;
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
-
import type {
|
|
3
|
-
import type { Options, ParseMediaFields } from '../../options';
|
|
4
|
-
import type { IsoBaseMediaBox, ParseResult } from '../../parse-result';
|
|
2
|
+
import type { ParseResult } from '../../parse-result';
|
|
5
3
|
import type { ParserState } from '../../state/parser-state';
|
|
6
|
-
export declare const
|
|
4
|
+
export declare const parseIsoBaseMedia: ({ iterator, state, }: {
|
|
7
5
|
iterator: BufferIterator;
|
|
8
|
-
maxBytes: number;
|
|
9
|
-
allowIncompleteBoxes: boolean;
|
|
10
|
-
initialBoxes: IsoBaseMediaBox[];
|
|
11
6
|
state: ParserState;
|
|
12
|
-
signal: AbortSignal | null;
|
|
13
|
-
logLevel: LogLevel;
|
|
14
|
-
fields: Options<ParseMediaFields>;
|
|
15
7
|
}) => Promise<ParseResult>;
|