@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.
Files changed (121) hide show
  1. package/dist/boxes/iso-base-media/continue-mdat-routine.d.ts +14 -0
  2. package/dist/boxes/iso-base-media/continue-mdat-routine.js +74 -0
  3. package/dist/boxes/iso-base-media/get-children.d.ts +2 -8
  4. package/dist/boxes/iso-base-media/get-children.js +14 -30
  5. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +3 -23
  6. package/dist/boxes/iso-base-media/mdat/mdat.js +80 -130
  7. package/dist/boxes/iso-base-media/moov/moov.d.ts +1 -6
  8. package/dist/boxes/iso-base-media/moov/moov.js +5 -14
  9. package/dist/boxes/iso-base-media/parse-all-children.d.ts +8 -0
  10. package/dist/boxes/iso-base-media/parse-all-children.js +20 -0
  11. package/dist/boxes/iso-base-media/parse-boxes.d.ts +2 -10
  12. package/dist/boxes/iso-base-media/parse-boxes.js +33 -116
  13. package/dist/boxes/iso-base-media/parse-mdat-partially.d.ts +1 -4
  14. package/dist/boxes/iso-base-media/parse-mdat-partially.js +2 -11
  15. package/dist/boxes/iso-base-media/process-box.d.ts +1 -9
  16. package/dist/boxes/iso-base-media/process-box.js +49 -143
  17. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +1 -4
  18. package/dist/boxes/iso-base-media/stsd/mebx.js +5 -14
  19. package/dist/boxes/iso-base-media/stsd/samples.d.ts +4 -12
  20. package/dist/boxes/iso-base-media/stsd/samples.js +24 -66
  21. package/dist/boxes/iso-base-media/stsd/stsd.d.ts +1 -4
  22. package/dist/boxes/iso-base-media/stsd/stsd.js +2 -5
  23. package/dist/boxes/iso-base-media/trak/trak.d.ts +1 -6
  24. package/dist/boxes/iso-base-media/trak/trak.js +5 -14
  25. package/dist/boxes/iso-base-media/traversal.d.ts +0 -2
  26. package/dist/boxes/iso-base-media/traversal.js +1 -12
  27. package/dist/boxes/mp3/id3.d.ts +1 -3
  28. package/dist/boxes/mp3/id3.js +7 -5
  29. package/dist/boxes/mp3/parse-mp3.d.ts +2 -3
  30. package/dist/boxes/mp3/parse-mp3.js +3 -19
  31. package/dist/boxes/riff/expect-riff-box.d.ts +1 -9
  32. package/dist/boxes/riff/expect-riff-box.js +47 -25
  33. package/dist/boxes/riff/get-tracks-from-avi.d.ts +1 -1
  34. package/dist/boxes/riff/get-tracks-from-avi.js +6 -10
  35. package/dist/boxes/riff/parse-fmt-box.d.ts +3 -2
  36. package/dist/boxes/riff/parse-fmt-box.js +7 -5
  37. package/dist/boxes/riff/parse-list-box.d.ts +1 -3
  38. package/dist/boxes/riff/parse-list-box.js +16 -16
  39. package/dist/boxes/riff/parse-movi.d.ts +2 -5
  40. package/dist/boxes/riff/parse-movi.js +34 -56
  41. package/dist/boxes/riff/parse-riff-body.d.ts +2 -6
  42. package/dist/boxes/riff/parse-riff-body.js +15 -95
  43. package/dist/boxes/riff/parse-riff-box.d.ts +1 -4
  44. package/dist/boxes/riff/parse-riff-box.js +3 -7
  45. package/dist/boxes/riff/parse-riff-header.d.ts +7 -0
  46. package/dist/boxes/riff/parse-riff-header.js +23 -0
  47. package/dist/boxes/riff/parse-riff.d.ts +7 -0
  48. package/dist/boxes/riff/parse-riff.js +15 -0
  49. package/dist/boxes/riff/parse-strf.d.ts +4 -4
  50. package/dist/boxes/riff/parse-strf.js +4 -8
  51. package/dist/boxes/riff/parse-strh.js +11 -0
  52. package/dist/boxes/riff/parse-video-section.d.ts +6 -0
  53. package/dist/boxes/riff/parse-video-section.js +20 -0
  54. package/dist/boxes/riff/riff-box.d.ts +4 -5
  55. package/dist/boxes/riff/traversal.d.ts +1 -2
  56. package/dist/boxes/riff/traversal.js +1 -6
  57. package/dist/boxes/transport-stream/get-tracks.d.ts +2 -3
  58. package/dist/boxes/transport-stream/get-tracks.js +4 -3
  59. package/dist/boxes/transport-stream/parse-packet.d.ts +1 -7
  60. package/dist/boxes/transport-stream/parse-packet.js +3 -4
  61. package/dist/boxes/transport-stream/parse-stream-packet.d.ts +1 -5
  62. package/dist/boxes/transport-stream/parse-stream-packet.js +10 -12
  63. package/dist/boxes/transport-stream/parse-transport-stream.d.ts +1 -7
  64. package/dist/boxes/transport-stream/parse-transport-stream.js +7 -26
  65. package/dist/boxes/transport-stream/process-stream-buffers.d.ts +1 -2
  66. package/dist/boxes/transport-stream/process-stream-buffers.js +3 -3
  67. package/dist/boxes/webm/parse-ebml.js +3 -0
  68. package/dist/boxes/webm/parse-webm-header.d.ts +2 -4
  69. package/dist/boxes/webm/parse-webm-header.js +41 -25
  70. package/dist/boxes/webm/segments/parse-children.d.ts +2 -16
  71. package/dist/boxes/webm/segments/parse-children.js +7 -130
  72. package/dist/boxes/webm/segments.d.ts +4 -8
  73. package/dist/boxes/webm/segments.js +41 -123
  74. package/dist/buffer-iterator.d.ts +0 -3
  75. package/dist/buffer-iterator.js +6 -16
  76. package/dist/bun-reader.d.ts +1 -0
  77. package/dist/bun-reader.js +17 -0
  78. package/dist/emit-available-info.js +4 -4
  79. package/dist/esm/from-node.mjs +8 -9
  80. package/dist/esm/index.mjs +4224 -4950
  81. package/dist/file-types/detect-file-type.js +4 -2
  82. package/dist/get-audio-codec.d.ts +1 -1
  83. package/dist/get-audio-codec.js +2 -2
  84. package/dist/get-dimensions.js +1 -1
  85. package/dist/get-duration.js +1 -1
  86. package/dist/get-is-hdr.d.ts +1 -1
  87. package/dist/get-is-hdr.js +2 -2
  88. package/dist/get-tracks.d.ts +1 -1
  89. package/dist/get-tracks.js +14 -13
  90. package/dist/get-video-codec.d.ts +1 -1
  91. package/dist/get-video-codec.js +2 -2
  92. package/dist/index.d.ts +50 -24
  93. package/dist/index.js +1 -1
  94. package/dist/may-skip-video-data/may-skip-video-data.js +6 -2
  95. package/dist/parse-media.js +45 -30
  96. package/dist/parse-result.d.ts +1 -18
  97. package/dist/parse-video.d.ts +3 -17
  98. package/dist/parse-video.js +45 -32
  99. package/dist/readers/from-node.js +7 -8
  100. package/dist/state/can-skip-tracks.d.ts +8 -1
  101. package/dist/state/can-skip-tracks.js +38 -27
  102. package/dist/state/iso-base-media/cached-sample-positions.d.ts +15 -0
  103. package/dist/state/iso-base-media/cached-sample-positions.js +42 -0
  104. package/dist/state/iso-base-media/iso-state.d.ts +8 -0
  105. package/dist/state/iso-base-media/iso-state.js +15 -0
  106. package/dist/state/iso-state.d.ts +4 -0
  107. package/dist/state/iso-state.js +13 -0
  108. package/dist/state/parser-state.d.ts +49 -14
  109. package/dist/state/parser-state.js +11 -3
  110. package/dist/state/sample-callbacks.d.ts +5 -1
  111. package/dist/state/sample-callbacks.js +4 -1
  112. package/dist/state/transport-stream.d.ts +8 -0
  113. package/dist/state/transport-stream.js +11 -0
  114. package/dist/state/video-section.d.ts +16 -0
  115. package/dist/state/video-section.js +37 -0
  116. package/dist/state/webm.d.ts +15 -0
  117. package/dist/state/webm.js +32 -0
  118. package/dist/version.d.ts +1 -1
  119. package/dist/version.js +1 -1
  120. package/package.json +3 -3
  121. 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 getChildren: ({ boxType, iterator, bytesRemainingInBox, state, signal, logLevel, fields, }: {
7
- boxType: string;
4
+ export declare const getIsoBaseMediaChildren: ({ iterator, state, size, }: {
8
5
  iterator: BufferIterator;
9
- bytesRemainingInBox: number;
10
6
  state: ParserState;
11
- signal: AbortSignal | null;
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.getChildren = void 0;
4
- const parse_boxes_1 = require("./parse-boxes");
5
- const getChildren = async ({ boxType, iterator, bytesRemainingInBox, state, signal, logLevel, fields, }) => {
6
- const parseChildren = boxType === 'mdia' ||
7
- boxType === 'minf' ||
8
- boxType === 'stbl' ||
9
- boxType === 'udta' ||
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.status === 'incomplete') {
29
- throw new Error('Incomplete boxes are not allowed');
13
+ if (!parsed.box) {
14
+ throw new Error('Expected box');
30
15
  }
31
- return boxes;
16
+ boxes.push(parsed.box);
32
17
  }
33
- if (bytesRemainingInBox < 0) {
34
- throw new Error('Box size is too big ' + JSON.stringify({ boxType }));
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
- iterator.discard(bytesRemainingInBox);
37
- return [];
21
+ return boxes;
38
22
  };
39
- exports.getChildren = getChildren;
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
- type MdatStatus = {
6
- status: 'samples-buffered';
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
- signal: AbortSignal | null;
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.parseMdat = void 0;
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 get_sample_positions_from_track_1 = require("../get-sample-positions-from-track");
7
- const traversal_1 = require("../traversal");
8
- const parseMdat = async ({ data, size, fileOffset, existingBoxes, state, signal, maySkipSampleProcessing, }) => {
9
- const alreadyHas = (0, get_tracks_1.getHasTracks)({
10
- type: 'iso-base-media',
11
- boxes: existingBoxes,
12
- }, state);
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
- if (maySkipSampleProcessing) {
15
- data.discard(size - (data.counter.getOffset() - fileOffset));
16
- return Promise.resolve({
17
- type: 'mdat-box',
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
- data.discard(size - (data.counter.getOffset() - fileOffset));
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
- const tracks = (0, get_tracks_1.getTracks)({ type: 'iso-base-media', boxes: existingBoxes }, state);
33
- const allTracks = [
34
- ...tracks.videoTracks,
35
- ...tracks.audioTracks,
36
- ...tracks.otherTracks,
37
- ];
38
- const flatSamples = allTracks
39
- .map((track) => {
40
- const samplePositions = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)(track.trakBox, (0, traversal_1.getMoofBox)(existingBoxes));
41
- if (!samplePositions) {
42
- throw new Error('No sample positions');
43
- }
44
- return samplePositions.map((samplePosition) => {
45
- return {
46
- track: { ...track },
47
- samplePosition,
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
- const expectedOffsetNow = size + fileOffset;
126
- const actualOffsetNow = data.counter.getOffset();
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
- return Promise.resolve({
135
- type: 'mdat-box',
136
- boxSize: size,
137
- status: 'samples-processed',
138
- fileOffset,
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.parseMdat = parseMdat;
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, signal, logLevel, fields, }: {
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 parse_boxes_1 = require("../parse-boxes");
5
- const parseMoov = async ({ iterator, offset, size, state, signal, logLevel, fields, }) => {
6
- const boxes = [];
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
- signal,
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: boxes,
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 { LogLevel } from '../../log';
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 parseIsoBaseMediaBoxes: ({ iterator, maxBytes, allowIncompleteBoxes, initialBoxes, state, signal, logLevel, fields, }: {
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>;