@remotion/media-parser 4.0.302 → 4.0.303
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/check-if-done.js +4 -0
- package/dist/containers/aac/parse-aac.js +1 -0
- package/dist/containers/avc/key.d.ts +1 -1
- package/dist/containers/avc/key.js +5 -1
- package/dist/containers/avc/max-buffer-size.d.ts +3 -0
- package/dist/containers/avc/max-buffer-size.js +40 -0
- package/dist/containers/avc/parse-avc.d.ts +6 -7
- package/dist/containers/avc/parse-avc.js +83 -7
- package/dist/containers/flac/parse-streaminfo.js +1 -0
- package/dist/containers/iso-base-media/base-media-box.d.ts +2 -1
- package/dist/containers/iso-base-media/elst.d.ts +19 -0
- package/dist/containers/iso-base-media/elst.js +33 -0
- package/dist/containers/iso-base-media/find-keyframe-before-time.d.ts +2 -1
- package/dist/containers/iso-base-media/find-keyframe-before-time.js +3 -3
- package/dist/containers/iso-base-media/get-moov-atom.js +1 -0
- package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +1 -0
- package/dist/containers/iso-base-media/get-seeking-byte.js +1 -0
- package/dist/containers/iso-base-media/make-track.d.ts +1 -1
- package/dist/containers/iso-base-media/make-track.js +4 -1
- package/dist/containers/iso-base-media/mdat/get-editlist.d.ts +5 -0
- package/dist/containers/iso-base-media/mdat/get-editlist.js +21 -0
- package/dist/containers/iso-base-media/mdat/mdat.js +8 -5
- package/dist/containers/iso-base-media/parse-boxes.js +1 -0
- package/dist/containers/iso-base-media/process-box.d.ts +2 -0
- package/dist/containers/iso-base-media/process-box.js +31 -4
- package/dist/containers/iso-base-media/traversal.d.ts +2 -0
- package/dist/containers/iso-base-media/traversal.js +10 -1
- package/dist/containers/mp3/parse-mpeg-header.js +1 -0
- package/dist/containers/riff/convert-queued-sample-to-mediaparser-sample.d.ts +14 -0
- package/dist/containers/riff/convert-queued-sample-to-mediaparser-sample.js +55 -0
- package/dist/containers/riff/get-seeking-byte.d.ts +3 -1
- package/dist/containers/riff/get-seeking-byte.js +5 -1
- package/dist/containers/riff/get-strh-for-index.d.ts +2 -0
- package/dist/containers/riff/get-strh-for-index.js +17 -0
- package/dist/containers/riff/get-tracks-from-avi.js +2 -0
- package/dist/containers/riff/parse-movi.js +51 -44
- package/dist/containers/riff/parse-riff-body.js +8 -0
- package/dist/containers/transport-stream/handle-aac-packet.js +1 -0
- package/dist/containers/transport-stream/handle-avc-packet.d.ts +3 -1
- package/dist/containers/transport-stream/handle-avc-packet.js +4 -3
- package/dist/containers/transport-stream/parse-transport-stream.js +1 -0
- package/dist/containers/transport-stream/process-audio.d.ts +3 -1
- package/dist/containers/transport-stream/process-audio.js +2 -1
- package/dist/containers/transport-stream/process-sample-if-possible.js +2 -0
- package/dist/containers/transport-stream/process-stream-buffers.d.ts +5 -2
- package/dist/containers/transport-stream/process-stream-buffers.js +4 -2
- package/dist/containers/transport-stream/process-video.d.ts +3 -1
- package/dist/containers/transport-stream/process-video.js +2 -1
- package/dist/containers/wav/parse-fmt.js +1 -0
- package/dist/containers/webm/get-sample-from-block.d.ts +3 -1
- package/dist/containers/webm/get-sample-from-block.js +4 -3
- package/dist/containers/webm/make-track.js +2 -0
- package/dist/containers/webm/parse-ebml.d.ts +1 -1
- package/dist/containers/webm/parse-ebml.js +3 -1
- package/dist/containers/webm/state-for-processing.d.ts +3 -1
- package/dist/containers/webm/state-for-processing.js +2 -1
- package/dist/convert-audio-or-video-sample.js +1 -0
- package/dist/esm/index.mjs +597 -127
- package/dist/esm/universal.mjs +9 -8
- package/dist/esm/web.mjs +9 -8
- package/dist/esm/worker-server-entry.mjs +596 -126
- package/dist/esm/worker-web-entry.mjs +596 -126
- package/dist/get-seeking-byte.d.ts +3 -1
- package/dist/get-seeking-byte.js +2 -1
- package/dist/get-tracks.d.ts +3 -0
- package/dist/get-tracks.js +10 -1
- package/dist/index.d.ts +34 -3
- package/dist/readers/from-fetch.js +2 -1
- package/dist/run-parse-iteration.js +0 -3
- package/dist/state/avc/avc-state.d.ts +12 -0
- package/dist/state/avc/avc-state.js +44 -0
- package/dist/state/iso-base-media/iso-state.d.ts +4 -0
- package/dist/state/iso-base-media/iso-state.js +2 -0
- package/dist/state/iso-base-media/timescale-state.d.ts +5 -0
- package/dist/state/iso-base-media/timescale-state.js +13 -0
- package/dist/state/parser-state.d.ts +34 -3
- package/dist/state/parser-state.js +3 -0
- package/dist/state/riff/queued-b-frames.d.ts +9 -0
- package/dist/state/riff/queued-b-frames.js +47 -0
- package/dist/state/riff/queued-frames.d.ts +9 -0
- package/dist/state/riff/queued-frames.js +39 -0
- package/dist/state/riff/riff-keyframes.js +1 -0
- package/dist/state/riff/sample-counter.d.ts +13 -2
- package/dist/state/riff/sample-counter.js +34 -7
- package/dist/state/riff.d.ts +19 -2
- package/dist/state/riff.js +3 -0
- package/dist/state/transport-stream/last-emitted-sample.d.ts +1 -1
- package/dist/state/transport-stream/transport-stream.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/webcodec-sample-types.d.ts +11 -0
- package/dist/work-on-seek-request.d.ts +2 -0
- package/dist/work-on-seek-request.js +5 -2
- package/package.json +3 -3
package/dist/check-if-done.js
CHANGED
|
@@ -19,6 +19,10 @@ const checkIfDone = async (state) => {
|
|
|
19
19
|
!state.m3u.getAllChunksProcessedOverall()) {
|
|
20
20
|
return false;
|
|
21
21
|
}
|
|
22
|
+
state.riff.queuedBFrames.flush();
|
|
23
|
+
if (state.riff.queuedBFrames.hasReleasedFrames()) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
22
26
|
log_1.Log.verbose(state.logLevel, 'Reached end of file');
|
|
23
27
|
await state.discardReadBytes(true);
|
|
24
28
|
return true;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { AvcInfo } from './parse-avc';
|
|
2
|
-
export declare const getKeyFrameOrDeltaFromAvcInfo: (infos: AvcInfo[]) => "key" | "delta";
|
|
2
|
+
export declare const getKeyFrameOrDeltaFromAvcInfo: (infos: AvcInfo[]) => "key" | "delta" | "bidirectional";
|
|
@@ -6,6 +6,10 @@ const getKeyFrameOrDeltaFromAvcInfo = (infos) => {
|
|
|
6
6
|
if (!keyOrDelta) {
|
|
7
7
|
throw new Error('expected avc to contain info about key or delta');
|
|
8
8
|
}
|
|
9
|
-
return keyOrDelta.type === 'keyframe'
|
|
9
|
+
return keyOrDelta.type === 'keyframe'
|
|
10
|
+
? 'key'
|
|
11
|
+
: keyOrDelta.isBidirectionalFrame
|
|
12
|
+
? 'bidirectional'
|
|
13
|
+
: 'delta';
|
|
10
14
|
};
|
|
11
15
|
exports.getKeyFrameOrDeltaFromAvcInfo = getKeyFrameOrDeltaFromAvcInfo;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.maxMacroblockBufferSize = exports.macroBlocksPerFrame = void 0;
|
|
4
|
+
// https://www.itu.int/rec/T-REC-H.264-202408-I
|
|
5
|
+
// Table A-1 – Level limits
|
|
6
|
+
const maxMacroblocksByLevel = {
|
|
7
|
+
10: 396, // Level 1.0
|
|
8
|
+
11: 900, // Level 1.1
|
|
9
|
+
12: 2376, // Level 1.2
|
|
10
|
+
13: 2376, // Level 1.3
|
|
11
|
+
20: 2376, // Level 2.0
|
|
12
|
+
21: 4752, // Level 2.1
|
|
13
|
+
22: 8100, // Level 2.2
|
|
14
|
+
30: 8100, // Level 3.0
|
|
15
|
+
31: 18000, // Level 3.1
|
|
16
|
+
32: 20480, // Level 3.2
|
|
17
|
+
40: 32768, // Level 4.0
|
|
18
|
+
41: 32768, // Level 4.1
|
|
19
|
+
42: 34816, // Level 4.2
|
|
20
|
+
50: 110400, // Level 5.0
|
|
21
|
+
51: 184320, // Level 5.1
|
|
22
|
+
52: 184320, // Level 5.2
|
|
23
|
+
60: 696320, // Level 6.0
|
|
24
|
+
61: 696320, // Level 6.1
|
|
25
|
+
62: 696320, // Level 6.2
|
|
26
|
+
};
|
|
27
|
+
const macroBlocksPerFrame = (sps) => {
|
|
28
|
+
const { pic_width_in_mbs_minus1, pic_height_in_map_units_minus1 } = sps;
|
|
29
|
+
return (pic_width_in_mbs_minus1 + 1) * (pic_height_in_map_units_minus1 + 1);
|
|
30
|
+
};
|
|
31
|
+
exports.macroBlocksPerFrame = macroBlocksPerFrame;
|
|
32
|
+
const maxMacroblockBufferSize = (sps) => {
|
|
33
|
+
const { level } = sps;
|
|
34
|
+
const maxMacroblocks = maxMacroblocksByLevel[level];
|
|
35
|
+
if (maxMacroblocks === undefined) {
|
|
36
|
+
throw new Error(`Unsupported level: ${level.toString(16)}`);
|
|
37
|
+
}
|
|
38
|
+
return maxMacroblocks;
|
|
39
|
+
};
|
|
40
|
+
exports.maxMacroblockBufferSize = maxMacroblockBufferSize;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { AvcState } from '../../state/avc/avc-state';
|
|
2
|
+
import type { MediaParserAvcDeltaFrameInfo, MediaParserAvcKeyframeInfo } from '../../webcodec-sample-types';
|
|
1
3
|
type VuiParameters = {
|
|
2
4
|
sar_width: number | null;
|
|
3
5
|
sar_height: number | null;
|
|
@@ -19,7 +21,7 @@ export type SpsInfo = {
|
|
|
19
21
|
bit_depth_luma_minus8: number | null;
|
|
20
22
|
bit_depth_chroma_minus8: number | null;
|
|
21
23
|
qpprime_y_zero_transform_bypass_flag: number | null;
|
|
22
|
-
log2_max_frame_num_minus4: number
|
|
24
|
+
log2_max_frame_num_minus4: number;
|
|
23
25
|
log2_max_pic_order_cnt_lsb_minus4: number | null;
|
|
24
26
|
max_num_ref_frames: number | null;
|
|
25
27
|
gaps_in_frame_num_value_allowed_flag: number | null;
|
|
@@ -32,6 +34,7 @@ export type SpsInfo = {
|
|
|
32
34
|
frame_crop_top_offset: number | null;
|
|
33
35
|
frame_crop_bottom_offset: number | null;
|
|
34
36
|
vui_parameters: VuiParameters | null;
|
|
37
|
+
pic_order_cnt_type: number;
|
|
35
38
|
};
|
|
36
39
|
export type AvcProfileInfo = {
|
|
37
40
|
spsData: SpsInfo;
|
|
@@ -42,10 +45,6 @@ export type AvcPPs = {
|
|
|
42
45
|
type: 'avc-pps';
|
|
43
46
|
pps: Uint8Array;
|
|
44
47
|
};
|
|
45
|
-
export type AvcInfo = AvcProfileInfo | AvcPPs |
|
|
46
|
-
|
|
47
|
-
} | {
|
|
48
|
-
type: 'delta-frame';
|
|
49
|
-
};
|
|
50
|
-
export declare const parseAvc: (buffer: Uint8Array) => AvcInfo[];
|
|
48
|
+
export type AvcInfo = AvcProfileInfo | AvcPPs | MediaParserAvcKeyframeInfo | MediaParserAvcDeltaFrameInfo;
|
|
49
|
+
export declare const parseAvc: (buffer: Uint8Array, avcState: AvcState) => AvcInfo[];
|
|
51
50
|
export {};
|
|
@@ -5,6 +5,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
5
5
|
exports.parseAvc = void 0;
|
|
6
6
|
const buffer_iterator_1 = require("../../iterator/buffer-iterator");
|
|
7
7
|
const Extended_SAR = 255;
|
|
8
|
+
const getPoc = (iterator, sps, avcState, isReferencePicture) => {
|
|
9
|
+
const { pic_order_cnt_type, log2_max_pic_order_cnt_lsb_minus4 } = sps;
|
|
10
|
+
if (pic_order_cnt_type !== 0) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const prevPicOrderCntLsb = avcState.getPrevPicOrderCntLsb();
|
|
14
|
+
const prevPicOrderCntMsb = avcState.getPrevPicOrderCntMsb();
|
|
15
|
+
if (log2_max_pic_order_cnt_lsb_minus4 === null) {
|
|
16
|
+
throw new Error('log2_max_pic_order_cnt_lsb_minus4 is null');
|
|
17
|
+
}
|
|
18
|
+
const max_pic_order_cnt_lsb = 2 ** (log2_max_pic_order_cnt_lsb_minus4 + 4);
|
|
19
|
+
const pic_order_cnt_lsb = iterator.getBits(log2_max_pic_order_cnt_lsb_minus4 + 4);
|
|
20
|
+
let picOrderCntMsb;
|
|
21
|
+
if (pic_order_cnt_lsb < prevPicOrderCntLsb &&
|
|
22
|
+
prevPicOrderCntLsb - pic_order_cnt_lsb >= max_pic_order_cnt_lsb / 2) {
|
|
23
|
+
picOrderCntMsb = prevPicOrderCntMsb + max_pic_order_cnt_lsb;
|
|
24
|
+
}
|
|
25
|
+
else if (pic_order_cnt_lsb > prevPicOrderCntLsb &&
|
|
26
|
+
pic_order_cnt_lsb - prevPicOrderCntLsb > max_pic_order_cnt_lsb / 2) {
|
|
27
|
+
picOrderCntMsb = prevPicOrderCntMsb - max_pic_order_cnt_lsb;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
picOrderCntMsb = prevPicOrderCntMsb;
|
|
31
|
+
}
|
|
32
|
+
const poc = picOrderCntMsb + pic_order_cnt_lsb;
|
|
33
|
+
if (isReferencePicture) {
|
|
34
|
+
avcState.setPrevPicOrderCntLsb(pic_order_cnt_lsb);
|
|
35
|
+
avcState.setPrevPicOrderCntMsb(picOrderCntMsb);
|
|
36
|
+
}
|
|
37
|
+
return poc;
|
|
38
|
+
};
|
|
8
39
|
const readVuiParameters = (iterator) => {
|
|
9
40
|
let sar_width = null;
|
|
10
41
|
let sar_height = null;
|
|
@@ -168,6 +199,7 @@ const readSps = (iterator) => {
|
|
|
168
199
|
frame_crop_top_offset,
|
|
169
200
|
mb_adaptive_frame_field_flag,
|
|
170
201
|
vui_parameters,
|
|
202
|
+
pic_order_cnt_type,
|
|
171
203
|
};
|
|
172
204
|
};
|
|
173
205
|
const findEnd = (buffer) => {
|
|
@@ -185,17 +217,23 @@ const findEnd = (buffer) => {
|
|
|
185
217
|
}
|
|
186
218
|
return null;
|
|
187
219
|
};
|
|
188
|
-
const inspect = (buffer) => {
|
|
220
|
+
const inspect = (buffer, avcState) => {
|
|
189
221
|
const iterator = (0, buffer_iterator_1.getArrayBufferIterator)(buffer, buffer.byteLength);
|
|
190
222
|
iterator.startReadingBits();
|
|
191
|
-
iterator.getBits(1);
|
|
192
|
-
iterator.getBits(2);
|
|
193
|
-
const
|
|
194
|
-
iterator.
|
|
223
|
+
iterator.getBits(1); // forbidden_zero_bit
|
|
224
|
+
const nal_ref_idc = iterator.getBits(2); // nal_ref_idc
|
|
225
|
+
const isReferencePicture = nal_ref_idc !== 0;
|
|
226
|
+
const type = iterator.getBits(5); // nal_unit_type
|
|
195
227
|
if (type === 7) {
|
|
228
|
+
iterator.stopReadingBits();
|
|
196
229
|
const end = findEnd(buffer);
|
|
197
230
|
const data = readSps(iterator);
|
|
198
231
|
const sps = buffer.slice(0, end === null ? Infinity : end);
|
|
232
|
+
avcState.setSps(data);
|
|
233
|
+
if (isReferencePicture) {
|
|
234
|
+
avcState.setPrevPicOrderCntLsb(0);
|
|
235
|
+
avcState.setPrevPicOrderCntMsb(0);
|
|
236
|
+
}
|
|
199
237
|
return {
|
|
200
238
|
spsData: data,
|
|
201
239
|
sps,
|
|
@@ -203,11 +241,31 @@ const inspect = (buffer) => {
|
|
|
203
241
|
};
|
|
204
242
|
}
|
|
205
243
|
if (type === 5) {
|
|
244
|
+
avcState.setPrevPicOrderCntLsb(0);
|
|
245
|
+
avcState.setPrevPicOrderCntMsb(0);
|
|
246
|
+
iterator.readExpGolomb(); // ignore first_mb_in_slice
|
|
247
|
+
iterator.readExpGolomb(); // slice_type
|
|
248
|
+
iterator.readExpGolomb(); // pic_parameter_set_id
|
|
249
|
+
const sps = avcState.getSps();
|
|
250
|
+
if (!sps) {
|
|
251
|
+
throw new Error('SPS not found');
|
|
252
|
+
}
|
|
253
|
+
const numberOfBitsForFrameNum = sps.log2_max_frame_num_minus4 + 4;
|
|
254
|
+
iterator.getBits(numberOfBitsForFrameNum); // frame_num
|
|
255
|
+
iterator.readExpGolomb(); // idr_pic_id
|
|
256
|
+
const { pic_order_cnt_type } = sps;
|
|
257
|
+
let poc = null;
|
|
258
|
+
if (pic_order_cnt_type === 0) {
|
|
259
|
+
poc = getPoc(iterator, sps, avcState, isReferencePicture);
|
|
260
|
+
}
|
|
261
|
+
iterator.stopReadingBits();
|
|
206
262
|
return {
|
|
207
263
|
type: 'keyframe',
|
|
264
|
+
poc,
|
|
208
265
|
};
|
|
209
266
|
}
|
|
210
267
|
if (type === 8) {
|
|
268
|
+
iterator.stopReadingBits();
|
|
211
269
|
const end = findEnd(buffer);
|
|
212
270
|
const pps = buffer.slice(0, end === null ? Infinity : end);
|
|
213
271
|
return {
|
|
@@ -216,15 +274,33 @@ const inspect = (buffer) => {
|
|
|
216
274
|
};
|
|
217
275
|
}
|
|
218
276
|
if (type === 1) {
|
|
277
|
+
iterator.readExpGolomb(); // ignore first_mb_in_slice
|
|
278
|
+
const slice_type = iterator.readExpGolomb();
|
|
279
|
+
const isBidirectionalFrame = slice_type === 6;
|
|
280
|
+
iterator.readExpGolomb(); // pic_parameter_set_id
|
|
281
|
+
const sps = avcState.getSps();
|
|
282
|
+
if (!sps) {
|
|
283
|
+
throw new Error('SPS not found');
|
|
284
|
+
}
|
|
285
|
+
const numberOfBitsForFrameNum = sps.log2_max_frame_num_minus4 + 4;
|
|
286
|
+
iterator.getBits(numberOfBitsForFrameNum); // frame_num
|
|
287
|
+
const { pic_order_cnt_type } = sps;
|
|
288
|
+
let poc = null;
|
|
289
|
+
if (pic_order_cnt_type === 0) {
|
|
290
|
+
poc = getPoc(iterator, sps, avcState, isReferencePicture);
|
|
291
|
+
}
|
|
292
|
+
iterator.stopReadingBits();
|
|
219
293
|
return {
|
|
220
294
|
type: 'delta-frame',
|
|
295
|
+
isBidirectionalFrame,
|
|
296
|
+
poc,
|
|
221
297
|
};
|
|
222
298
|
}
|
|
223
299
|
iterator.destroy();
|
|
224
300
|
return null;
|
|
225
301
|
};
|
|
226
302
|
// https://stackoverflow.com/questions/24884827/possible-locations-for-sequence-picture-parameter-sets-for-h-264-stream
|
|
227
|
-
const parseAvc = (buffer) => {
|
|
303
|
+
const parseAvc = (buffer, avcState) => {
|
|
228
304
|
let zeroesInARow = 0;
|
|
229
305
|
const infos = [];
|
|
230
306
|
for (let i = 0; i < buffer.length; i++) {
|
|
@@ -235,7 +311,7 @@ const parseAvc = (buffer) => {
|
|
|
235
311
|
}
|
|
236
312
|
if (zeroesInARow >= 2 && val === 1) {
|
|
237
313
|
zeroesInARow = 0;
|
|
238
|
-
const info = inspect(buffer.slice(i + 1, i + 100));
|
|
314
|
+
const info = inspect(buffer.slice(i + 1, i + 100), avcState);
|
|
239
315
|
if (info) {
|
|
240
316
|
infos.push(info);
|
|
241
317
|
if (info.type === 'keyframe' || info.type === 'delta-frame') {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BaseBox } from './base-type';
|
|
2
|
+
import type { ElstBox } from './elst';
|
|
2
3
|
import type { EsdsBox } from './esds/esds';
|
|
3
4
|
import type { FtypBox } from './ftyp';
|
|
4
5
|
import type { MdhdBox } from './mdhd';
|
|
@@ -34,4 +35,4 @@ export interface RegularBox extends BaseBox {
|
|
|
34
35
|
offset: number;
|
|
35
36
|
type: 'regular-box';
|
|
36
37
|
}
|
|
37
|
-
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | IlstBox | EsdsBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | HdlrBox | ColorParameterBox | TfdtBox | TfhdBox | TfraBox;
|
|
38
|
+
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | ElstBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | IlstBox | EsdsBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | HdlrBox | ColorParameterBox | TfdtBox | TfhdBox | TfraBox;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../iterator/buffer-iterator';
|
|
2
|
+
import type { BaseBox } from './base-type';
|
|
3
|
+
export interface ElstBox extends BaseBox {
|
|
4
|
+
type: 'elst-box';
|
|
5
|
+
version: number;
|
|
6
|
+
flags: number;
|
|
7
|
+
entries: ElstEntry[];
|
|
8
|
+
}
|
|
9
|
+
export type ElstEntry = {
|
|
10
|
+
editDuration: number;
|
|
11
|
+
mediaTime: number;
|
|
12
|
+
mediaRateInteger: number;
|
|
13
|
+
mediaRateFraction: number;
|
|
14
|
+
};
|
|
15
|
+
export declare const parseElst: ({ iterator, size, offset, }: {
|
|
16
|
+
iterator: BufferIterator;
|
|
17
|
+
size: number;
|
|
18
|
+
offset: number;
|
|
19
|
+
}) => ElstBox;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseElst = void 0;
|
|
4
|
+
const parseElst = ({ iterator, size, offset, }) => {
|
|
5
|
+
const { expectNoMoreBytes } = iterator.startBox(size - 8);
|
|
6
|
+
const version = iterator.getUint8();
|
|
7
|
+
const flags = iterator.getUint24();
|
|
8
|
+
const entryCount = iterator.getUint32();
|
|
9
|
+
const entries = [];
|
|
10
|
+
for (let i = 0; i < entryCount; i++) {
|
|
11
|
+
const editDuration = iterator.getUint32();
|
|
12
|
+
const mediaTime = iterator.getInt32();
|
|
13
|
+
const mediaRateInteger = iterator.getUint16();
|
|
14
|
+
const mediaRateFraction = iterator.getUint16();
|
|
15
|
+
entries.push({
|
|
16
|
+
editDuration,
|
|
17
|
+
mediaTime,
|
|
18
|
+
mediaRateInteger,
|
|
19
|
+
mediaRateFraction,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
expectNoMoreBytes();
|
|
23
|
+
const result = {
|
|
24
|
+
type: 'elst-box',
|
|
25
|
+
version,
|
|
26
|
+
flags,
|
|
27
|
+
entries,
|
|
28
|
+
boxSize: size,
|
|
29
|
+
offset,
|
|
30
|
+
};
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
exports.parseElst = parseElst;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { SamplePosition } from '../../get-sample-positions';
|
|
2
2
|
import type { MediaParserLogLevel } from '../../log';
|
|
3
3
|
import type { MediaSection } from '../../state/video-section';
|
|
4
|
-
export declare const findKeyframeBeforeTime: ({ samplePositions, time, timescale, mediaSections, logLevel, }: {
|
|
4
|
+
export declare const findKeyframeBeforeTime: ({ samplePositions, time, timescale, mediaSections, logLevel, startInSeconds, }: {
|
|
5
5
|
samplePositions: SamplePosition[];
|
|
6
6
|
time: number;
|
|
7
7
|
timescale: number;
|
|
8
8
|
mediaSections: MediaSection[];
|
|
9
9
|
logLevel: MediaParserLogLevel;
|
|
10
|
+
startInSeconds: number;
|
|
10
11
|
}) => number | null;
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.findKeyframeBeforeTime = void 0;
|
|
4
4
|
const log_1 = require("../../log");
|
|
5
|
-
const findKeyframeBeforeTime = ({ samplePositions, time, timescale, mediaSections, logLevel, }) => {
|
|
5
|
+
const findKeyframeBeforeTime = ({ samplePositions, time, timescale, mediaSections, logLevel, startInSeconds, }) => {
|
|
6
6
|
let videoByte = 0;
|
|
7
7
|
let videoSample = null;
|
|
8
8
|
for (const sample of samplePositions) {
|
|
9
|
-
const ctsInSeconds = sample.cts / timescale;
|
|
10
|
-
const dtsInSeconds = sample.dts / timescale;
|
|
9
|
+
const ctsInSeconds = sample.cts / timescale + startInSeconds;
|
|
10
|
+
const dtsInSeconds = sample.dts / timescale + startInSeconds;
|
|
11
11
|
if (!sample.isKeyframe) {
|
|
12
12
|
continue;
|
|
13
13
|
}
|
|
@@ -79,6 +79,7 @@ const getMoovAtom = async ({ endOfMdat, state, }) => {
|
|
|
79
79
|
onlyIfMoovAtomExpected: {
|
|
80
80
|
tracks: tracksState,
|
|
81
81
|
isoState: null,
|
|
82
|
+
movieTimeScaleState: state.iso.movieTimeScale,
|
|
82
83
|
onAudioTrack,
|
|
83
84
|
onVideoTrack,
|
|
84
85
|
registerVideoSampleCallback: () => Promise.resolve(),
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { MediaParserAudioTrack, MediaParserOtherTrack, MediaParserVideoTrack } from '../../get-tracks';
|
|
2
2
|
import type { TrakBox } from './trak/trak';
|
|
3
|
-
export declare const makeBaseMediaTrack: (trakBox: TrakBox) => MediaParserVideoTrack | MediaParserAudioTrack | MediaParserOtherTrack | null;
|
|
3
|
+
export declare const makeBaseMediaTrack: (trakBox: TrakBox, startTimeInSeconds: number) => MediaParserVideoTrack | MediaParserAudioTrack | MediaParserOtherTrack | null;
|
|
@@ -9,7 +9,7 @@ const color_to_webcodecs_colors_1 = require("./color-to-webcodecs-colors");
|
|
|
9
9
|
const get_actual_number_of_channels_1 = require("./get-actual-number-of-channels");
|
|
10
10
|
const get_video_codec_from_iso_track_1 = require("./get-video-codec-from-iso-track");
|
|
11
11
|
const traversal_1 = require("./traversal");
|
|
12
|
-
const makeBaseMediaTrack = (trakBox) => {
|
|
12
|
+
const makeBaseMediaTrack = (trakBox, startTimeInSeconds) => {
|
|
13
13
|
var _a, _b, _c, _d, _e;
|
|
14
14
|
const tkhdBox = (0, traversal_1.getTkhdBox)(trakBox);
|
|
15
15
|
const videoDescriptors = (0, traversal_1.getVideoDescriptors)(trakBox);
|
|
@@ -48,6 +48,7 @@ const makeBaseMediaTrack = (trakBox) => {
|
|
|
48
48
|
description: (_d = (_c = actual.codecPrivate) === null || _c === void 0 ? void 0 : _c.data) !== null && _d !== void 0 ? _d : undefined,
|
|
49
49
|
codecData: actual.codecPrivate,
|
|
50
50
|
codecEnum,
|
|
51
|
+
startInSeconds: startTimeInSeconds,
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
if (!(0, get_fps_1.trakBoxContainsVideo)(trakBox)) {
|
|
@@ -56,6 +57,7 @@ const makeBaseMediaTrack = (trakBox) => {
|
|
|
56
57
|
trackId: tkhdBox.trackId,
|
|
57
58
|
timescale: timescaleAndDuration.timescale,
|
|
58
59
|
trakBox,
|
|
60
|
+
startInSeconds: startTimeInSeconds,
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
63
|
const videoSample = (0, get_sample_aspect_ratio_1.getStsdVideoConfig)(trakBox);
|
|
@@ -104,6 +106,7 @@ const makeBaseMediaTrack = (trakBox) => {
|
|
|
104
106
|
advancedColor,
|
|
105
107
|
codecEnum: (0, get_video_codec_from_iso_track_1.getVideoCodecFromIsoTrak)(trakBox),
|
|
106
108
|
fps: (0, get_fps_1.getFpsFromMp4TrakBox)(trakBox),
|
|
109
|
+
startInSeconds: startTimeInSeconds,
|
|
107
110
|
};
|
|
108
111
|
return track;
|
|
109
112
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findTrackStartTimeInSeconds = void 0;
|
|
4
|
+
const traversal_1 = require("../traversal");
|
|
5
|
+
const findTrackStartTimeInSeconds = ({ movieTimeScale, trakBox, }) => {
|
|
6
|
+
const elstBox = (0, traversal_1.getElstBox)(trakBox);
|
|
7
|
+
if (!elstBox) {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
const { entries } = elstBox;
|
|
11
|
+
let dwellTime = 0;
|
|
12
|
+
for (const entry of entries) {
|
|
13
|
+
const { editDuration, mediaTime } = entry;
|
|
14
|
+
if (mediaTime !== -1) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
dwellTime += editDuration;
|
|
18
|
+
}
|
|
19
|
+
return dwellTime / movieTimeScale;
|
|
20
|
+
};
|
|
21
|
+
exports.findTrackStartTimeInSeconds = findTrackStartTimeInSeconds;
|
|
@@ -107,7 +107,10 @@ const parseMdatSection = async (state) => {
|
|
|
107
107
|
if (iterator.bytesRemaining() < samplesWithIndex.samplePosition.size) {
|
|
108
108
|
return (0, skip_1.makeFetchMoreData)(samplesWithIndex.samplePosition.size - iterator.bytesRemaining());
|
|
109
109
|
}
|
|
110
|
-
const { cts, dts, duration, isKeyframe, offset, bigEndian, chunkSize } = samplesWithIndex.samplePosition;
|
|
110
|
+
const { cts: rawCts, dts: rawDts, duration, isKeyframe, offset, bigEndian, chunkSize, } = samplesWithIndex.samplePosition;
|
|
111
|
+
const { timescale, startInSeconds } = samplesWithIndex.track;
|
|
112
|
+
const cts = rawCts + startInSeconds * timescale;
|
|
113
|
+
const dts = rawDts + startInSeconds * timescale;
|
|
111
114
|
const bytes = (0, postprocess_bytes_1.postprocessBytes)({
|
|
112
115
|
bytes: iterator.getSlice(samplesWithIndex.samplePosition.size),
|
|
113
116
|
bigEndian,
|
|
@@ -124,9 +127,9 @@ const parseMdatSection = async (state) => {
|
|
|
124
127
|
trackId: samplesWithIndex.track.trackId,
|
|
125
128
|
type: isKeyframe ? 'key' : 'delta',
|
|
126
129
|
offset,
|
|
127
|
-
timescale
|
|
130
|
+
timescale,
|
|
128
131
|
},
|
|
129
|
-
timescale
|
|
132
|
+
timescale,
|
|
130
133
|
});
|
|
131
134
|
await state.callbacks.onAudioSample(samplesWithIndex.track.trackId, audioSample);
|
|
132
135
|
}
|
|
@@ -153,9 +156,9 @@ const parseMdatSection = async (state) => {
|
|
|
153
156
|
trackId: samplesWithIndex.track.trackId,
|
|
154
157
|
type: isKeyframe && !isRecoveryPoint ? 'key' : 'delta',
|
|
155
158
|
offset,
|
|
156
|
-
timescale
|
|
159
|
+
timescale,
|
|
157
160
|
},
|
|
158
|
-
timescale
|
|
161
|
+
timescale,
|
|
159
162
|
});
|
|
160
163
|
await state.callbacks.onVideoSample(samplesWithIndex.track.trackId, videoSample);
|
|
161
164
|
}
|
|
@@ -15,6 +15,7 @@ const parseIsoBaseMedia = async (state) => {
|
|
|
15
15
|
onlyIfMoovAtomExpected: {
|
|
16
16
|
tracks: state.callbacks.tracks,
|
|
17
17
|
isoState: state.iso,
|
|
18
|
+
movieTimeScaleState: state.iso.movieTimeScale,
|
|
18
19
|
onAudioTrack: state.onAudioTrack,
|
|
19
20
|
onVideoTrack: state.onVideoTrack,
|
|
20
21
|
registerAudioSampleCallback: state.callbacks.registerAudioSampleCallback,
|
|
@@ -3,6 +3,7 @@ import type { MediaParserLogLevel } from '../../log';
|
|
|
3
3
|
import type { FetchMoreData } from '../../skip';
|
|
4
4
|
import type { TracksState } from '../../state/has-tracks-section';
|
|
5
5
|
import type { IsoBaseMediaState } from '../../state/iso-base-media/iso-state';
|
|
6
|
+
import type { MovieTimeScaleState } from '../../state/iso-base-media/timescale-state';
|
|
6
7
|
import type { CallbacksState } from '../../state/sample-callbacks';
|
|
7
8
|
import type { MediaSectionState } from '../../state/video-section';
|
|
8
9
|
import type { MediaParserOnAudioTrack, MediaParserOnVideoTrack } from '../../webcodec-sample-types';
|
|
@@ -10,6 +11,7 @@ import type { IsoBaseMediaBox } from './base-media-box';
|
|
|
10
11
|
export type OnlyIfMoovAtomExpected = {
|
|
11
12
|
tracks: TracksState;
|
|
12
13
|
isoState: IsoBaseMediaState | null;
|
|
14
|
+
movieTimeScaleState: MovieTimeScaleState;
|
|
13
15
|
onVideoTrack: MediaParserOnVideoTrack | null;
|
|
14
16
|
onAudioTrack: MediaParserOnAudioTrack | null;
|
|
15
17
|
registerVideoSampleCallback: CallbacksState['registerVideoSampleCallback'];
|
|
@@ -4,10 +4,12 @@ exports.processBox = void 0;
|
|
|
4
4
|
const log_1 = require("../../log");
|
|
5
5
|
const register_track_1 = require("../../register-track");
|
|
6
6
|
const skip_1 = require("../../skip");
|
|
7
|
+
const elst_1 = require("./elst");
|
|
7
8
|
const esds_1 = require("./esds/esds");
|
|
8
9
|
const ftyp_1 = require("./ftyp");
|
|
9
10
|
const get_children_1 = require("./get-children");
|
|
10
11
|
const make_track_1 = require("./make-track");
|
|
12
|
+
const get_editlist_1 = require("./mdat/get-editlist");
|
|
11
13
|
const mdhd_1 = require("./mdhd");
|
|
12
14
|
const hdlr_1 = require("./meta/hdlr");
|
|
13
15
|
const ilst_1 = require("./meta/ilst");
|
|
@@ -84,6 +86,16 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
84
86
|
box: (0, ftyp_1.parseFtyp)({ iterator, size: boxSize, offset: fileOffset }),
|
|
85
87
|
};
|
|
86
88
|
}
|
|
89
|
+
if (boxType === 'elst') {
|
|
90
|
+
return {
|
|
91
|
+
type: 'box',
|
|
92
|
+
box: (0, elst_1.parseElst)({
|
|
93
|
+
iterator,
|
|
94
|
+
size: boxSize,
|
|
95
|
+
offset: fileOffset,
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
87
99
|
if (boxType === 'colr') {
|
|
88
100
|
return {
|
|
89
101
|
type: 'box',
|
|
@@ -94,9 +106,18 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
94
106
|
};
|
|
95
107
|
}
|
|
96
108
|
if (boxType === 'mvhd') {
|
|
109
|
+
const mvhdBox = (0, mvhd_1.parseMvhd)({
|
|
110
|
+
iterator,
|
|
111
|
+
offset: fileOffset,
|
|
112
|
+
size: boxSize,
|
|
113
|
+
});
|
|
114
|
+
if (!onlyIfMoovAtomExpected) {
|
|
115
|
+
throw new Error('State is required');
|
|
116
|
+
}
|
|
117
|
+
onlyIfMoovAtomExpected.movieTimeScaleState.setTrackTimescale(mvhdBox.timeScale);
|
|
97
118
|
return {
|
|
98
119
|
type: 'box',
|
|
99
|
-
box:
|
|
120
|
+
box: mvhdBox,
|
|
100
121
|
};
|
|
101
122
|
}
|
|
102
123
|
if (boxType === 'tkhd') {
|
|
@@ -266,14 +287,19 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
266
287
|
throw new Error('State is required');
|
|
267
288
|
}
|
|
268
289
|
const { tracks, onAudioTrack, onVideoTrack } = onlyIfMoovAtomExpected;
|
|
269
|
-
const
|
|
290
|
+
const trakBox = await (0, trak_1.parseTrak)({
|
|
270
291
|
size: boxSize,
|
|
271
292
|
offsetAtStart: fileOffset,
|
|
272
293
|
iterator,
|
|
273
294
|
logLevel,
|
|
274
295
|
contentLength,
|
|
275
296
|
});
|
|
276
|
-
const
|
|
297
|
+
const movieTimeScale = onlyIfMoovAtomExpected.movieTimeScaleState.getTrackTimescale();
|
|
298
|
+
if (movieTimeScale === null) {
|
|
299
|
+
throw new Error('Movie timescale is not set');
|
|
300
|
+
}
|
|
301
|
+
const editList = (0, get_editlist_1.findTrackStartTimeInSeconds)({ movieTimeScale, trakBox });
|
|
302
|
+
const transformedTrack = (0, make_track_1.makeBaseMediaTrack)(trakBox, editList);
|
|
277
303
|
if (transformedTrack && transformedTrack.type === 'video') {
|
|
278
304
|
await (0, register_track_1.registerVideoTrack)({
|
|
279
305
|
track: transformedTrack,
|
|
@@ -294,7 +320,7 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
294
320
|
onAudioTrack,
|
|
295
321
|
});
|
|
296
322
|
}
|
|
297
|
-
return { type: 'box', box };
|
|
323
|
+
return { type: 'box', box: trakBox };
|
|
298
324
|
}
|
|
299
325
|
if (boxType === 'stts') {
|
|
300
326
|
return {
|
|
@@ -377,6 +403,7 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
377
403
|
boxType === 'wave' ||
|
|
378
404
|
boxType === 'traf' ||
|
|
379
405
|
boxType === 'mfra' ||
|
|
406
|
+
boxType === 'edts' ||
|
|
380
407
|
boxType === 'stsb') {
|
|
381
408
|
const children = await (0, get_children_1.getIsoBaseMediaChildren)({
|
|
382
409
|
iterator,
|
|
@@ -3,6 +3,7 @@ import type { IsoBaseMediaState } from '../../state/iso-base-media/iso-state';
|
|
|
3
3
|
import type { MoofBox } from '../../state/iso-base-media/precomputed-moof';
|
|
4
4
|
import type { StructureState } from '../../state/structure';
|
|
5
5
|
import type { IsoBaseMediaBox, RegularBox } from './base-media-box';
|
|
6
|
+
import type { ElstBox } from './elst';
|
|
6
7
|
import type { FtypBox } from './ftyp';
|
|
7
8
|
import type { MdhdBox } from './mdhd';
|
|
8
9
|
import type { TfraBox } from './mfra/tfra';
|
|
@@ -49,3 +50,4 @@ export declare const getTrunBoxes: (segment: IsoBaseMediaBox) => TrunBox[];
|
|
|
49
50
|
export declare const getTfraBoxesFromMfraBoxChildren: (mfraBoxChildren: IsoBaseMediaBox[]) => TfraBox[];
|
|
50
51
|
export declare const getTfraBoxes: (structure: IsoBaseMediaBox[]) => TfraBox[];
|
|
51
52
|
export declare const getTrakBoxByTrackId: (moovBox: MoovBox, trackId: number) => TrakBox | null;
|
|
53
|
+
export declare const getElstBox: (trakBox: TrakBox) => ElstBox | null;
|