@remotion/media-parser 4.0.290 → 4.0.291
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/containers/iso-base-media/base-media-box.d.ts +0 -1
- package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.d.ts +4 -1
- package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.js +9 -5
- package/dist/containers/iso-base-media/find-keyframe-before-time.js +16 -11
- package/dist/containers/iso-base-media/find-track-to-seek.d.ts +14 -0
- package/dist/containers/iso-base-media/find-track-to-seek.js +39 -0
- package/dist/containers/iso-base-media/get-children.js +2 -2
- package/dist/containers/iso-base-media/get-keyframes.js +6 -1
- package/dist/containers/iso-base-media/get-mfra-seeking-box.d.ts +3 -1
- package/dist/containers/iso-base-media/get-mfra-seeking-box.js +5 -1
- package/dist/containers/iso-base-media/get-moov-atom.js +6 -3
- package/dist/containers/iso-base-media/get-sample-position-bounds.js +3 -1
- package/dist/containers/iso-base-media/get-sample-positions-from-track.js +1 -1
- package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.d.ts +14 -0
- package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +89 -0
- package/dist/containers/iso-base-media/get-seeking-byte.d.ts +3 -3
- package/dist/containers/iso-base-media/get-seeking-byte.js +32 -96
- package/dist/containers/iso-base-media/mdat/calculate-jump-marks.d.ts +6 -0
- package/dist/containers/iso-base-media/mdat/calculate-jump-marks.js +131 -0
- package/dist/containers/iso-base-media/mdat/mdat.d.ts +2 -2
- package/dist/containers/iso-base-media/mdat/mdat.js +18 -2
- package/dist/containers/iso-base-media/mfra/find-best-segment-from-tfra.d.ts +3 -3
- package/dist/containers/iso-base-media/mfra/find-best-segment-from-tfra.js +2 -2
- package/dist/containers/iso-base-media/mfra/get-mfra-atom.d.ts +5 -1
- package/dist/containers/iso-base-media/mfra/get-mfra-atom.js +3 -1
- package/dist/containers/iso-base-media/mfra/get-mfro-atom.d.ts +5 -1
- package/dist/containers/iso-base-media/mfra/get-mfro-atom.js +3 -1
- package/dist/containers/iso-base-media/parse-boxes.js +5 -2
- package/dist/containers/iso-base-media/process-box.d.ts +16 -5
- package/dist/containers/iso-base-media/process-box.js +206 -118
- package/dist/containers/iso-base-media/sample-positions.d.ts +25 -0
- package/dist/containers/iso-base-media/sample-positions.js +37 -0
- package/dist/containers/iso-base-media/stsd/samples.js +1 -0
- package/dist/containers/iso-base-media/stsd/stsc.d.ts +1 -6
- package/dist/containers/iso-base-media/stsd/stsc.js +2 -5
- package/dist/containers/iso-base-media/stsd/stss.d.ts +1 -1
- package/dist/containers/iso-base-media/stsd/stss.js +2 -2
- package/dist/containers/iso-base-media/turn-sample-positions-into-array.d.ts +19 -0
- package/dist/containers/iso-base-media/turn-sample-positions-into-array.js +73 -0
- package/dist/containers/m3u/after-manifest-fetch.d.ts +5 -1
- package/dist/containers/m3u/after-manifest-fetch.js +3 -1
- package/dist/containers/m3u/first-sample-in-m3u-chunk.d.ts +13 -0
- package/dist/containers/m3u/first-sample-in-m3u-chunk.js +31 -0
- package/dist/containers/m3u/get-seeking-byte.d.ts +13 -0
- package/dist/containers/m3u/get-seeking-byte.js +32 -0
- package/dist/containers/m3u/get-streams.d.ts +1 -0
- package/dist/containers/m3u/get-streams.js +1 -0
- package/dist/containers/m3u/iterate-over-segment-files.d.ts +5 -3
- package/dist/containers/m3u/iterate-over-segment-files.js +11 -1
- package/dist/containers/m3u/parse-m3u-media-directive.js +1 -0
- package/dist/containers/m3u/parse-m3u.js +8 -0
- package/dist/containers/m3u/process-m3u-chunk.d.ts +12 -0
- package/dist/containers/m3u/process-m3u-chunk.js +274 -0
- package/dist/containers/m3u/run-over-m3u.js +7 -80
- package/dist/containers/m3u/sample-sorter.d.ts +1 -0
- package/dist/containers/m3u/sample-sorter.js +4 -1
- package/dist/containers/m3u/seek/get-chunk-to-seek-to.d.ts +5 -0
- package/dist/containers/m3u/seek/get-chunk-to-seek-to.js +14 -0
- package/dist/containers/m3u/seeking-hints.d.ts +2 -0
- package/dist/containers/m3u/seeking-hints.js +9 -0
- package/dist/containers/m3u/select-stream.d.ts +2 -1
- package/dist/containers/m3u/select-stream.js +7 -2
- package/dist/containers/m3u/types.d.ts +1 -0
- package/dist/containers/riff/seek/fetch-idx1.d.ts +3 -1
- package/dist/containers/riff/seek/fetch-idx1.js +3 -1
- package/dist/containers/transport-stream/handle-aac-packet.d.ts +2 -2
- package/dist/containers/transport-stream/handle-avc-packet.d.ts +2 -2
- package/dist/containers/transport-stream/process-audio.d.ts +2 -2
- package/dist/containers/transport-stream/process-stream-buffers.d.ts +3 -3
- package/dist/containers/transport-stream/process-video.d.ts +2 -2
- package/dist/containers/webm/get-sample-from-block.d.ts +12 -2
- package/dist/containers/webm/get-sample-from-block.js +40 -9
- package/dist/containers/webm/parse-ebml.js +28 -10
- package/dist/containers/webm/seek/fetch-web-cues.d.ts +3 -1
- package/dist/containers/webm/seek/fetch-web-cues.js +3 -1
- package/dist/containers/webm/state-for-processing.d.ts +2 -2
- package/dist/controller/media-parser-controller.d.ts +1 -1
- package/dist/controller/media-parser-controller.js +6 -2
- package/dist/controller/seek-signal.d.ts +1 -5
- package/dist/download-and-parse-media.js +1 -1
- package/dist/esm/index.mjs +1400 -611
- package/dist/esm/node.mjs +23 -3
- package/dist/esm/server-worker.mjs +8 -1
- package/dist/esm/universal.mjs +168 -15
- package/dist/esm/web.mjs +145 -13
- package/dist/esm/worker-server-entry.mjs +1467 -635
- package/dist/esm/worker-web-entry.mjs +1439 -634
- package/dist/esm/worker.mjs +8 -1
- package/dist/get-audio-codec.js +3 -0
- package/dist/get-duration.js +2 -1
- package/dist/get-fps.js +2 -1
- package/dist/get-sample-positions-from-mp4.js +10 -5
- package/dist/get-sample-positions.js +4 -4
- package/dist/get-seeking-byte.d.ts +5 -3
- package/dist/get-seeking-byte.js +19 -10
- package/dist/get-seeking-hints.d.ts +3 -3
- package/dist/get-seeking-hints.js +18 -13
- package/dist/get-tracks.d.ts +9 -1
- package/dist/get-tracks.js +13 -6
- package/dist/index.d.ts +21 -5
- package/dist/init-video.js +3 -2
- package/dist/internal-parse-media.js +13 -4
- package/dist/iterator/buffer-iterator.js +5 -3
- package/dist/metadata/metadata-from-iso.js +2 -1
- package/dist/options.d.ts +6 -1
- package/dist/parse-loop.js +22 -6
- package/dist/parse-media-on-worker-entry.js +1 -0
- package/dist/parse-media.js +1 -1
- package/dist/parse-result.d.ts +2 -2
- package/dist/perform-seek.d.ts +3 -1
- package/dist/perform-seek.js +3 -1
- package/dist/readers/fetch/get-body-and-reader.js +17 -2
- package/dist/readers/from-fetch.d.ts +17 -1
- package/dist/readers/from-fetch.js +68 -13
- package/dist/readers/from-node.js +24 -2
- package/dist/readers/from-web-file.js +3 -0
- package/dist/readers/reader.d.ts +19 -2
- package/dist/readers/universal.js +9 -0
- package/dist/readers/web.js +6 -0
- package/dist/register-track.d.ts +3 -3
- package/dist/seek-backwards.d.ts +3 -1
- package/dist/seek-backwards.js +4 -1
- package/dist/seek-forwards.d.ts +3 -1
- package/dist/seek-forwards.js +3 -1
- package/dist/seeking-hints.d.ts +4 -1
- package/dist/set-seeking-hints.js +4 -0
- package/dist/skip.d.ts +5 -0
- package/dist/skip.js +6 -1
- package/dist/state/can-skip-tracks.d.ts +1 -0
- package/dist/state/can-skip-tracks.js +10 -6
- package/dist/state/iso-base-media/cached-sample-positions.d.ts +15 -1
- package/dist/state/iso-base-media/cached-sample-positions.js +9 -4
- package/dist/state/iso-base-media/iso-state.d.ts +5 -1
- package/dist/state/iso-base-media/iso-state.js +2 -1
- package/dist/state/iso-base-media/lazy-mfra-load.d.ts +3 -1
- package/dist/state/iso-base-media/lazy-mfra-load.js +2 -1
- package/dist/state/keyframes.js +1 -0
- package/dist/state/m3u-state.d.ts +15 -4
- package/dist/state/m3u-state.js +20 -0
- package/dist/state/matroska/lazy-cues-fetch.d.ts +3 -1
- package/dist/state/matroska/lazy-cues-fetch.js +2 -1
- package/dist/state/matroska/webm.d.ts +3 -1
- package/dist/state/matroska/webm.js +2 -1
- package/dist/state/parser-state.d.ts +29 -13
- package/dist/state/parser-state.js +19 -5
- package/dist/state/riff/lazy-idx1-fetch.d.ts +3 -1
- package/dist/state/riff/lazy-idx1-fetch.js +2 -1
- package/dist/state/riff.d.ts +3 -1
- package/dist/state/riff.js +2 -1
- package/dist/state/sample-callbacks.d.ts +3 -2
- package/dist/state/sample-callbacks.js +3 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/work-on-seek-request.d.ts +6 -3
- package/dist/work-on-seek-request.js +13 -13
- package/dist/worker/forward-controller-to-worker.js +1 -1
- package/dist/worker/serialize-error.js +26 -3
- package/dist/worker/worker-types.d.ts +7 -1
- package/dist/worker-server.js +2 -2
- package/package.json +3 -3
|
@@ -34,5 +34,4 @@ export interface RegularBox extends BaseBox {
|
|
|
34
34
|
offset: number;
|
|
35
35
|
type: 'regular-box';
|
|
36
36
|
}
|
|
37
|
-
export type BoxAndNext = IsoBaseMediaBox | null;
|
|
38
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;
|
|
@@ -6,6 +6,9 @@ export declare const collectSamplePositionsFromMoofBoxes: ({ moofBoxes, tfraBoxe
|
|
|
6
6
|
tfraBoxes: TfraBox[];
|
|
7
7
|
tkhdBox: TkhdBox;
|
|
8
8
|
}) => {
|
|
9
|
-
samplePositions:
|
|
9
|
+
samplePositions: {
|
|
10
|
+
isLastFragment: boolean;
|
|
11
|
+
samples: import("../..").SamplePosition[];
|
|
12
|
+
}[];
|
|
10
13
|
isComplete: boolean;
|
|
11
14
|
};
|
|
@@ -5,11 +5,15 @@ const samples_from_moof_1 = require("../../samples-from-moof");
|
|
|
5
5
|
const collectSamplePositionsFromMoofBoxes = ({ moofBoxes, tfraBoxes, tkhdBox, }) => {
|
|
6
6
|
const isComplete = tfraBoxes.length > 0 &&
|
|
7
7
|
tfraBoxes.every((t) => t.entries.length === moofBoxes.length);
|
|
8
|
-
const samplePositions = moofBoxes.map((m) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
const samplePositions = moofBoxes.map((m, index) => {
|
|
9
|
+
const isLastFragment = index === moofBoxes.length - 1 && isComplete;
|
|
10
|
+
return {
|
|
11
|
+
isLastFragment,
|
|
12
|
+
samples: (0, samples_from_moof_1.getSamplesFromMoof)({
|
|
13
|
+
moofBox: m,
|
|
14
|
+
trackId: tkhdBox.trackId,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
13
17
|
});
|
|
14
18
|
return { samplePositions, isComplete };
|
|
15
19
|
};
|
|
@@ -3,26 +3,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.findKeyframeBeforeTime = void 0;
|
|
4
4
|
const log_1 = require("../../log");
|
|
5
5
|
const findKeyframeBeforeTime = ({ samplePositions, time, timescale, mediaSections, logLevel, }) => {
|
|
6
|
-
let
|
|
7
|
-
let
|
|
6
|
+
let videoByte = 0;
|
|
7
|
+
let videoSample = null;
|
|
8
8
|
for (const sample of samplePositions) {
|
|
9
9
|
const ctsInSeconds = sample.cts / timescale;
|
|
10
10
|
const dtsInSeconds = sample.dts / timescale;
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
if (!sample.isKeyframe) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (!(ctsInSeconds <= time || dtsInSeconds <= time)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (videoByte <= sample.offset) {
|
|
18
|
+
videoByte = sample.offset;
|
|
19
|
+
videoSample = sample;
|
|
16
20
|
}
|
|
17
21
|
}
|
|
18
|
-
if (!
|
|
22
|
+
if (!videoSample) {
|
|
19
23
|
throw new Error('No sample found');
|
|
20
24
|
}
|
|
21
|
-
const mediaSection = mediaSections.find((section) =>
|
|
25
|
+
const mediaSection = mediaSections.find((section) => videoSample.offset >= section.start &&
|
|
26
|
+
videoSample.offset < section.start + section.size);
|
|
22
27
|
if (!mediaSection) {
|
|
23
|
-
log_1.Log.trace(logLevel, 'Found a sample, but the offset has not yet been marked as a video section yet. Not yet able to seek, but probably once we have started reading the next box.',
|
|
28
|
+
log_1.Log.trace(logLevel, 'Found a sample, but the offset has not yet been marked as a video section yet. Not yet able to seek, but probably once we have started reading the next box.', videoSample);
|
|
24
29
|
return null;
|
|
25
30
|
}
|
|
26
|
-
return
|
|
31
|
+
return videoSample.offset;
|
|
27
32
|
};
|
|
28
33
|
exports.findKeyframeBeforeTime = findKeyframeBeforeTime;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SamplePosition } from '../../get-sample-positions';
|
|
2
|
+
import type { AudioTrack, OtherTrack, VideoTrack } from '../../get-tracks';
|
|
3
|
+
import type { IsoBaseMediaStructure } from '../../parse-result';
|
|
4
|
+
import type { StructureState } from '../../state/structure';
|
|
5
|
+
export declare const findAnyTrackWithSamplePositions: (allTracks: (VideoTrack | AudioTrack | OtherTrack)[], struc: IsoBaseMediaStructure) => {
|
|
6
|
+
track: VideoTrack | AudioTrack;
|
|
7
|
+
samplePositions: SamplePosition[];
|
|
8
|
+
} | null;
|
|
9
|
+
type TrackWithSamplePositions = {
|
|
10
|
+
track: VideoTrack | AudioTrack;
|
|
11
|
+
samplePositions: SamplePosition[];
|
|
12
|
+
};
|
|
13
|
+
export declare const findTrackToSeek: (allTracks: (VideoTrack | AudioTrack | OtherTrack)[], structure: StructureState) => TrackWithSamplePositions | null;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findTrackToSeek = exports.findAnyTrackWithSamplePositions = void 0;
|
|
4
|
+
const get_sample_positions_from_track_1 = require("./get-sample-positions-from-track");
|
|
5
|
+
const traversal_1 = require("./traversal");
|
|
6
|
+
const findAnyTrackWithSamplePositions = (allTracks, struc) => {
|
|
7
|
+
for (const track of allTracks) {
|
|
8
|
+
if (track.type === 'video' || track.type === 'audio') {
|
|
9
|
+
const { samplePositions } = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)({
|
|
10
|
+
trakBox: track.trakBox,
|
|
11
|
+
moofBoxes: (0, traversal_1.getMoofBoxes)(struc.boxes),
|
|
12
|
+
tfraBoxes: (0, traversal_1.getTfraBoxes)(struc),
|
|
13
|
+
});
|
|
14
|
+
if (samplePositions.length === 0) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
return { track, samplePositions };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
};
|
|
22
|
+
exports.findAnyTrackWithSamplePositions = findAnyTrackWithSamplePositions;
|
|
23
|
+
const findTrackToSeek = (allTracks, structure) => {
|
|
24
|
+
const firstVideoTrack = allTracks.find((t) => t.type === 'video');
|
|
25
|
+
const struc = structure.getIsoStructure();
|
|
26
|
+
if (!firstVideoTrack) {
|
|
27
|
+
return (0, exports.findAnyTrackWithSamplePositions)(allTracks, struc);
|
|
28
|
+
}
|
|
29
|
+
const { samplePositions } = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)({
|
|
30
|
+
trakBox: firstVideoTrack.trakBox,
|
|
31
|
+
moofBoxes: (0, traversal_1.getMoofBoxes)(struc.boxes),
|
|
32
|
+
tfraBoxes: (0, traversal_1.getTfraBoxes)(struc),
|
|
33
|
+
});
|
|
34
|
+
if (samplePositions.length === 0) {
|
|
35
|
+
return (0, exports.findAnyTrackWithSamplePositions)(allTracks, struc);
|
|
36
|
+
}
|
|
37
|
+
return { track: firstVideoTrack, samplePositions };
|
|
38
|
+
};
|
|
39
|
+
exports.findTrackToSeek = findTrackToSeek;
|
|
@@ -13,10 +13,10 @@ const getIsoBaseMediaChildren = async ({ size, iterator, logLevel, onlyIfMoovAto
|
|
|
13
13
|
onlyIfMdatAtomExpected: null,
|
|
14
14
|
contentLength,
|
|
15
15
|
});
|
|
16
|
-
if (
|
|
16
|
+
if (parsed.type !== 'box') {
|
|
17
17
|
throw new Error('Expected box');
|
|
18
18
|
}
|
|
19
|
-
boxes.push(parsed);
|
|
19
|
+
boxes.push(parsed.box);
|
|
20
20
|
}
|
|
21
21
|
if (iterator.counter.getOffset() > size + initial) {
|
|
22
22
|
throw new Error(`read too many bytes - size: ${size}, read: ${iterator.counter.getOffset() - initial}. initial offset: ${initial}`);
|
|
@@ -5,7 +5,12 @@ const get_tracks_1 = require("../../get-tracks");
|
|
|
5
5
|
const get_sample_positions_from_track_1 = require("./get-sample-positions-from-track");
|
|
6
6
|
const traversal_1 = require("./traversal");
|
|
7
7
|
const getKeyframesFromIsoBaseMedia = (state) => {
|
|
8
|
-
const { videoTracks } = (0, get_tracks_1.getTracksFromIsoBaseMedia)(
|
|
8
|
+
const { videoTracks } = (0, get_tracks_1.getTracksFromIsoBaseMedia)({
|
|
9
|
+
isoState: state.iso,
|
|
10
|
+
m3uPlaylistContext: state.m3uPlaylistContext,
|
|
11
|
+
structure: state.structure,
|
|
12
|
+
mayUsePrecomputed: true,
|
|
13
|
+
});
|
|
9
14
|
const structure = state.structure.getIsoStructure();
|
|
10
15
|
const moofBoxes = (0, traversal_1.getMoofBoxes)(structure.boxes);
|
|
11
16
|
const tfraBoxes = (0, traversal_1.getTfraBoxes)(structure);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MediaParserController } from '../../controller/media-parser-controller';
|
|
2
|
+
import type { PrefetchCache } from '../../fetch';
|
|
2
3
|
import type { LogLevel } from '../../log';
|
|
3
4
|
import type { ParseMediaSrc } from '../../options';
|
|
4
5
|
import type { ReaderInterface } from '../../readers/reader';
|
|
@@ -9,5 +10,6 @@ export type MfraSeekingBoxOptions = {
|
|
|
9
10
|
readerInterface: ReaderInterface;
|
|
10
11
|
src: ParseMediaSrc;
|
|
11
12
|
logLevel: LogLevel;
|
|
13
|
+
prefetchCache: PrefetchCache;
|
|
12
14
|
};
|
|
13
|
-
export declare const getMfraSeekingBox: ({ contentLength, controller, readerInterface, src, logLevel, }: MfraSeekingBoxOptions) => Promise<IsoBaseMediaBox[] | null>;
|
|
15
|
+
export declare const getMfraSeekingBox: ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }: MfraSeekingBoxOptions) => Promise<IsoBaseMediaBox[] | null>;
|
|
@@ -4,12 +4,14 @@ exports.getMfraSeekingBox = void 0;
|
|
|
4
4
|
const get_children_1 = require("./get-children");
|
|
5
5
|
const get_mfra_atom_1 = require("./mfra/get-mfra-atom");
|
|
6
6
|
const get_mfro_atom_1 = require("./mfra/get-mfro-atom");
|
|
7
|
-
const getMfraSeekingBox = async ({ contentLength, controller, readerInterface, src, logLevel, }) => {
|
|
7
|
+
const getMfraSeekingBox = async ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }) => {
|
|
8
8
|
const parentSize = await (0, get_mfro_atom_1.getMfroAtom)({
|
|
9
9
|
contentLength,
|
|
10
10
|
controller,
|
|
11
11
|
readerInterface,
|
|
12
12
|
src,
|
|
13
|
+
logLevel,
|
|
14
|
+
prefetchCache,
|
|
13
15
|
});
|
|
14
16
|
if (!parentSize) {
|
|
15
17
|
return null;
|
|
@@ -20,6 +22,8 @@ const getMfraSeekingBox = async ({ contentLength, controller, readerInterface, s
|
|
|
20
22
|
readerInterface,
|
|
21
23
|
src,
|
|
22
24
|
parentSize,
|
|
25
|
+
logLevel,
|
|
26
|
+
prefetchCache,
|
|
23
27
|
});
|
|
24
28
|
mfraAtom.discard(8);
|
|
25
29
|
return (0, get_children_1.getIsoBaseMediaChildren)({
|
|
@@ -10,7 +10,8 @@ const structure_1 = require("../../state/structure");
|
|
|
10
10
|
const process_box_1 = require("./process-box");
|
|
11
11
|
const traversal_1 = require("./traversal");
|
|
12
12
|
const getMoovAtom = async ({ endOfMdat, state, }) => {
|
|
13
|
-
|
|
13
|
+
var _a;
|
|
14
|
+
const headerSegment = (_a = state.m3uPlaylistContext) === null || _a === void 0 ? void 0 : _a.mp4HeaderSegment;
|
|
14
15
|
if (headerSegment) {
|
|
15
16
|
const segment = (0, traversal_1.getMoovFromFromIsoStructure)(headerSegment);
|
|
16
17
|
if (!segment) {
|
|
@@ -24,6 +25,8 @@ const getMoovAtom = async ({ endOfMdat, state, }) => {
|
|
|
24
25
|
src: state.src,
|
|
25
26
|
range: endOfMdat,
|
|
26
27
|
controller: state.controller,
|
|
28
|
+
logLevel: state.logLevel,
|
|
29
|
+
prefetchCache: state.prefetchCache,
|
|
27
30
|
});
|
|
28
31
|
const onAudioTrack = state.onAudioTrack
|
|
29
32
|
? async ({ track, container }) => {
|
|
@@ -84,8 +87,8 @@ const getMoovAtom = async ({ endOfMdat, state, }) => {
|
|
|
84
87
|
onlyIfMdatAtomExpected: null,
|
|
85
88
|
contentLength: state.contentLength - endOfMdat,
|
|
86
89
|
});
|
|
87
|
-
if (box) {
|
|
88
|
-
boxes.push(box);
|
|
90
|
+
if (box.type === 'box') {
|
|
91
|
+
boxes.push(box.box);
|
|
89
92
|
}
|
|
90
93
|
if (iterator.counter.getOffset() + endOfMdat > state.contentLength) {
|
|
91
94
|
throw new Error('Read past end of file');
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getSamplePositionBounds = void 0;
|
|
4
4
|
const getSamplePositionBounds = (samplePositions, timescale) => {
|
|
5
|
+
var _a;
|
|
5
6
|
let min = Infinity;
|
|
6
7
|
let max = -Infinity;
|
|
7
8
|
for (const samplePosition of samplePositions) {
|
|
8
9
|
const timestampMin = Math.min(samplePosition.cts, samplePosition.dts);
|
|
9
|
-
const timestampMax = Math.max(samplePosition.cts, samplePosition.dts)
|
|
10
|
+
const timestampMax = Math.max(samplePosition.cts, samplePosition.dts) +
|
|
11
|
+
((_a = samplePosition.duration) !== null && _a !== void 0 ? _a : 0);
|
|
10
12
|
if (timestampMin < min) {
|
|
11
13
|
min = timestampMin;
|
|
12
14
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AudioTrack, OtherTrack, VideoTrack } from '../../get-tracks';
|
|
2
|
+
import type { LogLevel } from '../../log';
|
|
3
|
+
import type { IsoBaseMediaSeekingHints } from '../../seeking-hints';
|
|
4
|
+
import type { IsoBaseMediaState } from '../../state/iso-base-media/iso-state';
|
|
5
|
+
import type { SeekResolution } from '../../work-on-seek-request';
|
|
6
|
+
export declare const getSeekingByteFromFragmentedMp4: ({ info, time, logLevel, currentPosition, isoState, allTracks, isLastChunkInPlaylist, }: {
|
|
7
|
+
info: IsoBaseMediaSeekingHints;
|
|
8
|
+
time: number;
|
|
9
|
+
logLevel: LogLevel;
|
|
10
|
+
currentPosition: number;
|
|
11
|
+
isoState: IsoBaseMediaState;
|
|
12
|
+
allTracks: (VideoTrack | AudioTrack | OtherTrack)[];
|
|
13
|
+
isLastChunkInPlaylist: boolean;
|
|
14
|
+
}) => Promise<SeekResolution>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSeekingByteFromFragmentedMp4 = void 0;
|
|
4
|
+
const log_1 = require("../../log");
|
|
5
|
+
const video_section_1 = require("../../state/video-section");
|
|
6
|
+
const collect_sample_positions_from_moof_boxes_1 = require("./collect-sample-positions-from-moof-boxes");
|
|
7
|
+
const find_keyframe_before_time_1 = require("./find-keyframe-before-time");
|
|
8
|
+
const get_sample_position_bounds_1 = require("./get-sample-position-bounds");
|
|
9
|
+
const find_best_segment_from_tfra_1 = require("./mfra/find-best-segment-from-tfra");
|
|
10
|
+
const traversal_1 = require("./traversal");
|
|
11
|
+
const getSeekingByteFromFragmentedMp4 = async ({ info, time, logLevel, currentPosition, isoState, allTracks, isLastChunkInPlaylist, }) => {
|
|
12
|
+
const firstVideoTrack = allTracks.find((t) => t.type === 'video');
|
|
13
|
+
// If there is both video and audio, seek based on video, but if not then audio is also okay
|
|
14
|
+
const firstTrack = firstVideoTrack !== null && firstVideoTrack !== void 0 ? firstVideoTrack : allTracks.find((t) => t.type === 'audio');
|
|
15
|
+
if (!firstTrack) {
|
|
16
|
+
throw new Error('no video and no audio tracks');
|
|
17
|
+
}
|
|
18
|
+
const tkhdBox = (0, traversal_1.getTkhdBox)(firstTrack.trakBox);
|
|
19
|
+
if (!tkhdBox) {
|
|
20
|
+
throw new Error('Expected tkhd box in trak box');
|
|
21
|
+
}
|
|
22
|
+
const { samplePositions: samplePositionsArray } = (0, collect_sample_positions_from_moof_boxes_1.collectSamplePositionsFromMoofBoxes)({
|
|
23
|
+
moofBoxes: info.moofBoxes,
|
|
24
|
+
tfraBoxes: info.tfraBoxes,
|
|
25
|
+
tkhdBox,
|
|
26
|
+
});
|
|
27
|
+
log_1.Log.trace(logLevel, 'Fragmented MP4 - Checking if we have seeking info for this time range');
|
|
28
|
+
for (const positions of samplePositionsArray) {
|
|
29
|
+
const { min, max } = (0, get_sample_position_bounds_1.getSamplePositionBounds)(positions.samples, firstTrack.timescale);
|
|
30
|
+
if (min <= time &&
|
|
31
|
+
(positions.isLastFragment || isLastChunkInPlaylist || time <= max)) {
|
|
32
|
+
log_1.Log.trace(logLevel, `Fragmented MP4 - Found that we have seeking info for this time range: ${min} <= ${time} <= ${max}`);
|
|
33
|
+
const kf = (0, find_keyframe_before_time_1.findKeyframeBeforeTime)({
|
|
34
|
+
samplePositions: positions.samples,
|
|
35
|
+
time,
|
|
36
|
+
timescale: firstTrack.timescale,
|
|
37
|
+
logLevel,
|
|
38
|
+
mediaSections: info.mediaSections,
|
|
39
|
+
});
|
|
40
|
+
if (kf) {
|
|
41
|
+
return {
|
|
42
|
+
type: 'do-seek',
|
|
43
|
+
byte: kf,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const atom = await (info.mfraAlreadyLoaded
|
|
49
|
+
? Promise.resolve(info.mfraAlreadyLoaded)
|
|
50
|
+
: isoState.mfra.triggerLoad());
|
|
51
|
+
if (atom) {
|
|
52
|
+
const moofOffset = (0, find_best_segment_from_tfra_1.findBestSegmentFromTfra)({
|
|
53
|
+
mfra: atom,
|
|
54
|
+
time,
|
|
55
|
+
firstTrack,
|
|
56
|
+
timescale: firstTrack.timescale,
|
|
57
|
+
});
|
|
58
|
+
if (moofOffset !== null &&
|
|
59
|
+
!(moofOffset.start <= currentPosition && currentPosition < moofOffset.end)) {
|
|
60
|
+
log_1.Log.verbose(logLevel, `Fragmented MP4 - Found based on mfra information that we should seek to: ${moofOffset.start} ${moofOffset.end}`);
|
|
61
|
+
return {
|
|
62
|
+
type: 'intermediary-seek',
|
|
63
|
+
byte: moofOffset.start,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
log_1.Log.trace(logLevel, 'Fragmented MP4 - No seeking info found for this time range.');
|
|
68
|
+
if ((0, video_section_1.isByteInMediaSection)({
|
|
69
|
+
position: currentPosition,
|
|
70
|
+
mediaSections: info.mediaSections,
|
|
71
|
+
}) !== 'in-section') {
|
|
72
|
+
return {
|
|
73
|
+
type: 'valid-but-must-wait',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
log_1.Log.trace(logLevel, 'Fragmented MP4 - Inside the wrong video section, skipping to the end of the section');
|
|
77
|
+
const mediaSection = (0, video_section_1.getCurrentMediaSection)({
|
|
78
|
+
offset: currentPosition,
|
|
79
|
+
mediaSections: info.mediaSections,
|
|
80
|
+
});
|
|
81
|
+
if (!mediaSection) {
|
|
82
|
+
throw new Error('No video section defined');
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
type: 'intermediary-seek',
|
|
86
|
+
byte: mediaSection.start + mediaSection.size,
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
exports.getSeekingByteFromFragmentedMp4 = getSeekingByteFromFragmentedMp4;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { LogLevel } from '../../log';
|
|
2
|
-
import type {
|
|
2
|
+
import type { M3uPlaylistContext } from '../../options';
|
|
3
3
|
import type { IsoBaseMediaSeekingHints } from '../../seeking-hints';
|
|
4
4
|
import type { IsoBaseMediaState } from '../../state/iso-base-media/iso-state';
|
|
5
5
|
import type { StructureState } from '../../state/structure';
|
|
6
6
|
import type { SeekResolution } from '../../work-on-seek-request';
|
|
7
|
-
export declare const getSeekingByteFromIsoBaseMedia: ({ info, time, logLevel, currentPosition, isoState,
|
|
7
|
+
export declare const getSeekingByteFromIsoBaseMedia: ({ info, time, logLevel, currentPosition, isoState, m3uPlaylistContext, structure, }: {
|
|
8
8
|
info: IsoBaseMediaSeekingHints;
|
|
9
9
|
time: number;
|
|
10
10
|
logLevel: LogLevel;
|
|
11
11
|
currentPosition: number;
|
|
12
12
|
isoState: IsoBaseMediaState;
|
|
13
|
-
|
|
13
|
+
m3uPlaylistContext: M3uPlaylistContext | null;
|
|
14
14
|
structure: StructureState;
|
|
15
15
|
}) => Promise<SeekResolution>;
|
|
@@ -3,132 +3,68 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getSeekingByteFromIsoBaseMedia = void 0;
|
|
4
4
|
const get_tracks_1 = require("../../get-tracks");
|
|
5
5
|
const log_1 = require("../../log");
|
|
6
|
-
const video_section_1 = require("../../state/video-section");
|
|
7
|
-
const collect_sample_positions_from_moof_boxes_1 = require("./collect-sample-positions-from-moof-boxes");
|
|
8
6
|
const find_keyframe_before_time_1 = require("./find-keyframe-before-time");
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const find_best_segment_from_tfra_1 = require("./mfra/find-best-segment-from-tfra");
|
|
7
|
+
const find_track_to_seek_1 = require("./find-track-to-seek");
|
|
8
|
+
const get_seeking_byte_from_fragmented_mp4_1 = require("./get-seeking-byte-from-fragmented-mp4");
|
|
12
9
|
const traversal_1 = require("./traversal");
|
|
13
|
-
const getSeekingByteFromIsoBaseMedia =
|
|
14
|
-
|
|
10
|
+
const getSeekingByteFromIsoBaseMedia = ({ info, time, logLevel, currentPosition, isoState, m3uPlaylistContext, structure, }) => {
|
|
11
|
+
var _a, _b;
|
|
12
|
+
const tracks = (0, get_tracks_1.getTracksFromIsoBaseMedia)({
|
|
13
|
+
isoState,
|
|
14
|
+
m3uPlaylistContext,
|
|
15
|
+
structure,
|
|
16
|
+
mayUsePrecomputed: false,
|
|
17
|
+
});
|
|
15
18
|
const allTracks = [
|
|
16
19
|
...tracks.videoTracks,
|
|
17
20
|
...tracks.audioTracks,
|
|
18
21
|
...tracks.otherTracks,
|
|
19
22
|
];
|
|
20
23
|
const hasMoov = Boolean((0, traversal_1.getMoovBoxFromState)({
|
|
21
|
-
mp4HeaderSegment,
|
|
22
24
|
structureState: structure,
|
|
23
25
|
isoState,
|
|
24
26
|
mayUsePrecomputed: false,
|
|
27
|
+
mp4HeaderSegment: (_a = m3uPlaylistContext === null || m3uPlaylistContext === void 0 ? void 0 : m3uPlaylistContext.mp4HeaderSegment) !== null && _a !== void 0 ? _a : null,
|
|
25
28
|
}));
|
|
26
29
|
if (!hasMoov) {
|
|
27
30
|
log_1.Log.trace(logLevel, 'No moov box found, must wait');
|
|
28
|
-
return {
|
|
31
|
+
return Promise.resolve({
|
|
29
32
|
type: 'valid-but-must-wait',
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
const firstVideoTrack = allTracks.find((t) => t.type === 'video');
|
|
33
|
-
if (!firstVideoTrack) {
|
|
34
|
-
throw new Error('No video track found');
|
|
33
|
+
});
|
|
35
34
|
}
|
|
36
|
-
const { timescale } = firstVideoTrack;
|
|
37
35
|
if (info.moofBoxes.length > 0) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
47
|
-
log_1.Log.trace(logLevel, 'Fragmented MP4 - Checking if we have seeking info for this time range');
|
|
48
|
-
for (const positions of samplePositionsArray) {
|
|
49
|
-
const { min, max } = (0, get_sample_position_bounds_1.getSamplePositionBounds)(positions, timescale);
|
|
50
|
-
if (min <= time && time <= max) {
|
|
51
|
-
log_1.Log.trace(logLevel, `Fragmented MP4 - Found that we have seeking info for this time range: ${min} <= ${time} <= ${max}`);
|
|
52
|
-
const kf = (0, find_keyframe_before_time_1.findKeyframeBeforeTime)({
|
|
53
|
-
samplePositions: positions,
|
|
54
|
-
time,
|
|
55
|
-
timescale,
|
|
56
|
-
logLevel,
|
|
57
|
-
mediaSections: info.mediaSections,
|
|
58
|
-
});
|
|
59
|
-
if (kf) {
|
|
60
|
-
return {
|
|
61
|
-
type: 'do-seek',
|
|
62
|
-
byte: kf,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const atom = await (info.mfraAlreadyLoaded
|
|
68
|
-
? Promise.resolve(info.mfraAlreadyLoaded)
|
|
69
|
-
: isoState.mfra.triggerLoad());
|
|
70
|
-
if (atom) {
|
|
71
|
-
const moofOffset = (0, find_best_segment_from_tfra_1.findBestSegmentFromTfra)({
|
|
72
|
-
mfra: atom,
|
|
73
|
-
time,
|
|
74
|
-
firstVideoTrack,
|
|
75
|
-
timescale,
|
|
76
|
-
});
|
|
77
|
-
if (moofOffset !== null &&
|
|
78
|
-
!(moofOffset.start <= currentPosition &&
|
|
79
|
-
currentPosition < moofOffset.end)) {
|
|
80
|
-
log_1.Log.verbose(logLevel, `Fragmented MP4 - Found based on mfra information that we should seek to: ${moofOffset.start} ${moofOffset.end}`);
|
|
81
|
-
return {
|
|
82
|
-
type: 'intermediary-seek',
|
|
83
|
-
byte: moofOffset.start,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
log_1.Log.trace(logLevel, 'Fragmented MP4 - No seeking info found for this time range.');
|
|
88
|
-
if ((0, video_section_1.isByteInMediaSection)({
|
|
89
|
-
position: currentPosition,
|
|
90
|
-
mediaSections: info.mediaSections,
|
|
91
|
-
}) !== 'in-section') {
|
|
92
|
-
return {
|
|
93
|
-
type: 'valid-but-must-wait',
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
log_1.Log.trace(logLevel, 'Fragmented MP4 - Inside the wrong video section, skipping to the end of the section');
|
|
97
|
-
const mediaSection = (0, video_section_1.getCurrentMediaSection)({
|
|
98
|
-
offset: currentPosition,
|
|
99
|
-
mediaSections: info.mediaSections,
|
|
36
|
+
return (0, get_seeking_byte_from_fragmented_mp4_1.getSeekingByteFromFragmentedMp4)({
|
|
37
|
+
info,
|
|
38
|
+
time,
|
|
39
|
+
logLevel,
|
|
40
|
+
currentPosition,
|
|
41
|
+
isoState,
|
|
42
|
+
allTracks,
|
|
43
|
+
isLastChunkInPlaylist: (_b = m3uPlaylistContext === null || m3uPlaylistContext === void 0 ? void 0 : m3uPlaylistContext.isLastChunkInPlaylist) !== null && _b !== void 0 ? _b : false,
|
|
100
44
|
});
|
|
101
|
-
if (!mediaSection) {
|
|
102
|
-
throw new Error('No video section defined');
|
|
103
|
-
}
|
|
104
|
-
return {
|
|
105
|
-
type: 'intermediary-seek',
|
|
106
|
-
byte: mediaSection.start + mediaSection.size,
|
|
107
|
-
};
|
|
108
45
|
}
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (!isComplete) {
|
|
115
|
-
throw new Error('Incomplete sample positions');
|
|
46
|
+
const trackWithSamplePositions = (0, find_track_to_seek_1.findTrackToSeek)(allTracks, structure);
|
|
47
|
+
if (!trackWithSamplePositions) {
|
|
48
|
+
return Promise.resolve({
|
|
49
|
+
type: 'valid-but-must-wait',
|
|
50
|
+
});
|
|
116
51
|
}
|
|
52
|
+
const { track, samplePositions } = trackWithSamplePositions;
|
|
117
53
|
const keyframe = (0, find_keyframe_before_time_1.findKeyframeBeforeTime)({
|
|
118
54
|
samplePositions,
|
|
119
55
|
time,
|
|
120
|
-
timescale,
|
|
56
|
+
timescale: track.timescale,
|
|
121
57
|
logLevel,
|
|
122
58
|
mediaSections: info.mediaSections,
|
|
123
59
|
});
|
|
124
60
|
if (keyframe) {
|
|
125
|
-
return {
|
|
61
|
+
return Promise.resolve({
|
|
126
62
|
type: 'do-seek',
|
|
127
63
|
byte: keyframe,
|
|
128
|
-
};
|
|
64
|
+
});
|
|
129
65
|
}
|
|
130
|
-
return {
|
|
66
|
+
return Promise.resolve({
|
|
131
67
|
type: 'invalid',
|
|
132
|
-
};
|
|
68
|
+
});
|
|
133
69
|
};
|
|
134
70
|
exports.getSeekingByteFromIsoBaseMedia = getSeekingByteFromIsoBaseMedia;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MinimalFlatSampleForTesting } from '../../../state/iso-base-media/cached-sample-positions';
|
|
2
|
+
export type JumpMark = {
|
|
3
|
+
afterSampleWithOffset: number;
|
|
4
|
+
jumpToOffset: number;
|
|
5
|
+
};
|
|
6
|
+
export declare const calculateJumpMarks: (samplePositionTracks: MinimalFlatSampleForTesting[][], endOfMdat: number) => JumpMark[];
|