Add .gitignore to exclude all node packages and lock files
This commit is contained in:
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
type AacSamplePosition = {
|
||||
offset: number;
|
||||
index: number;
|
||||
size: number;
|
||||
};
|
||||
export declare const aacState: () => {
|
||||
addSample: ({ offset, size }: {
|
||||
offset: number;
|
||||
size: number;
|
||||
}) => AacSamplePosition;
|
||||
getSamples: () => AacSamplePosition[];
|
||||
audioSamples: {
|
||||
addSample: (audioSampleOffset: import("./audio-sample-map").AudioSampleOffset) => void;
|
||||
getSamples: () => import("./audio-sample-map").AudioSampleOffset[];
|
||||
setFromSeekingHints: (newMap: import("./audio-sample-map").AudioSampleOffset[]) => void;
|
||||
};
|
||||
};
|
||||
export type AacState = ReturnType<typeof aacState>;
|
||||
export {};
|
||||
Generated
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.aacState = void 0;
|
||||
const audio_sample_map_1 = require("./audio-sample-map");
|
||||
const aacState = () => {
|
||||
const samples = [];
|
||||
// seems redunant, we could deduplicate this
|
||||
const audioSamples = (0, audio_sample_map_1.audioSampleMapState)();
|
||||
return {
|
||||
addSample: ({ offset, size }) => {
|
||||
const index = samples.findIndex((s) => s.offset === offset);
|
||||
if (index !== -1) {
|
||||
return samples[index];
|
||||
}
|
||||
samples.push({ offset, index: samples.length, size });
|
||||
return samples[samples.length - 1];
|
||||
},
|
||||
getSamples: () => samples,
|
||||
audioSamples,
|
||||
};
|
||||
};
|
||||
exports.aacState = aacState;
|
||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
export type AudioSampleOffset = {
|
||||
timeInSeconds: number;
|
||||
offset: number;
|
||||
durationInSeconds: number;
|
||||
};
|
||||
export declare const audioSampleMapState: () => {
|
||||
addSample: (audioSampleOffset: AudioSampleOffset) => void;
|
||||
getSamples: () => AudioSampleOffset[];
|
||||
setFromSeekingHints: (newMap: AudioSampleOffset[]) => void;
|
||||
};
|
||||
export type AudioSampleMapState = ReturnType<typeof audioSampleMapState>;
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.audioSampleMapState = void 0;
|
||||
const audioSampleMapState = () => {
|
||||
// {[]}
|
||||
let map = [];
|
||||
const addSample = (audioSampleOffset) => {
|
||||
if (map.find((m) => m.offset === audioSampleOffset.offset)) {
|
||||
return;
|
||||
}
|
||||
map.push(audioSampleOffset);
|
||||
};
|
||||
return {
|
||||
addSample,
|
||||
getSamples: () => map,
|
||||
setFromSeekingHints: (newMap) => {
|
||||
map = newMap;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.audioSampleMapState = audioSampleMapState;
|
||||
Generated
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
import type { SpsInfo } from '../../containers/avc/parse-avc';
|
||||
export declare const avcState: () => {
|
||||
getPrevPicOrderCntLsb(): number;
|
||||
getPrevPicOrderCntMsb(): number;
|
||||
setPrevPicOrderCntLsb(value: number): void;
|
||||
setPrevPicOrderCntMsb(value: number): void;
|
||||
setSps(value: SpsInfo): void;
|
||||
getSps(): SpsInfo | null;
|
||||
getMaxFramesInBuffer(): number | null;
|
||||
clear(): void;
|
||||
};
|
||||
export type AvcState = ReturnType<typeof avcState>;
|
||||
Generated
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.avcState = void 0;
|
||||
const max_buffer_size_1 = require("../../containers/avc/max-buffer-size");
|
||||
const avcState = () => {
|
||||
let prevPicOrderCntLsb = 0;
|
||||
let prevPicOrderCntMsb = 0;
|
||||
let sps = null;
|
||||
let maxFramesInBuffer = null;
|
||||
return {
|
||||
getPrevPicOrderCntLsb() {
|
||||
return prevPicOrderCntLsb;
|
||||
},
|
||||
getPrevPicOrderCntMsb() {
|
||||
return prevPicOrderCntMsb;
|
||||
},
|
||||
setPrevPicOrderCntLsb(value) {
|
||||
prevPicOrderCntLsb = value;
|
||||
},
|
||||
setPrevPicOrderCntMsb(value) {
|
||||
prevPicOrderCntMsb = value;
|
||||
},
|
||||
setSps(value) {
|
||||
const macroblockBufferSize = (0, max_buffer_size_1.macroBlocksPerFrame)(value);
|
||||
const maxBufferSize = (0, max_buffer_size_1.maxMacroblockBufferSize)(value);
|
||||
const maxFrames = Math.min(16, Math.floor(maxBufferSize / macroblockBufferSize));
|
||||
maxFramesInBuffer = maxFrames;
|
||||
sps = value;
|
||||
},
|
||||
getSps() {
|
||||
return sps;
|
||||
},
|
||||
getMaxFramesInBuffer() {
|
||||
return maxFramesInBuffer;
|
||||
},
|
||||
clear() {
|
||||
maxFramesInBuffer = null;
|
||||
sps = null;
|
||||
prevPicOrderCntLsb = 0;
|
||||
prevPicOrderCntMsb = 0;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.avcState = avcState;
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
import type { Options, ParseMediaFields } from '../fields';
|
||||
import type { MediaParserStructureUnstable } from '../parse-result';
|
||||
import type { StructureState } from './structure';
|
||||
export declare const needsTracksForField: ({ field, structure, }: {
|
||||
field: keyof Options<ParseMediaFields>;
|
||||
structure: MediaParserStructureUnstable | null;
|
||||
}) => boolean;
|
||||
export declare const makeCanSkipTracksState: ({ hasAudioTrackHandlers, fields, hasVideoTrackHandlers, structure, }: {
|
||||
hasAudioTrackHandlers: boolean;
|
||||
hasVideoTrackHandlers: boolean;
|
||||
fields: Options<ParseMediaFields>;
|
||||
structure: StructureState;
|
||||
}) => {
|
||||
doFieldsNeedTracks: () => boolean;
|
||||
canSkipTracks: () => boolean;
|
||||
};
|
||||
export type CanSkipTracksState = ReturnType<typeof makeCanSkipTracksState>;
|
||||
Generated
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeCanSkipTracksState = exports.needsTracksForField = void 0;
|
||||
const needsTracksForField = ({ field, structure, }) => {
|
||||
if (field === 'dimensions') {
|
||||
if ((structure === null || structure === void 0 ? void 0 : structure.type) === 'riff') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (field === 'audioCodec' ||
|
||||
field === 'durationInSeconds' ||
|
||||
field === 'slowDurationInSeconds' ||
|
||||
field === 'slowFps' ||
|
||||
field === 'fps' ||
|
||||
field === 'isHdr' ||
|
||||
field === 'rotation' ||
|
||||
field === 'slowStructure' ||
|
||||
field === 'tracks' ||
|
||||
field === 'unrotatedDimensions' ||
|
||||
field === 'videoCodec' ||
|
||||
field === 'metadata' ||
|
||||
field === 'location' ||
|
||||
field === 'slowKeyframes' ||
|
||||
field === 'slowNumberOfFrames' ||
|
||||
field === 'keyframes' ||
|
||||
field === 'images' ||
|
||||
field === 'sampleRate' ||
|
||||
field === 'numberOfAudioChannels' ||
|
||||
field === 'slowAudioBitrate' ||
|
||||
field === 'slowVideoBitrate' ||
|
||||
field === 'm3uStreams') {
|
||||
return true;
|
||||
}
|
||||
if (field === 'container' ||
|
||||
field === 'internalStats' ||
|
||||
field === 'mimeType' ||
|
||||
field === 'name' ||
|
||||
field === 'size') {
|
||||
return false;
|
||||
}
|
||||
throw new Error(`field not implemeted ${field}`);
|
||||
};
|
||||
exports.needsTracksForField = needsTracksForField;
|
||||
const makeCanSkipTracksState = ({ hasAudioTrackHandlers, fields, hasVideoTrackHandlers, structure, }) => {
|
||||
const doFieldsNeedTracks = () => {
|
||||
const keys = Object.keys(fields !== null && fields !== void 0 ? fields : {});
|
||||
const selectedKeys = keys.filter((k) => fields[k]);
|
||||
return selectedKeys.some((k) => (0, exports.needsTracksForField)({
|
||||
field: k,
|
||||
structure: structure.getStructureOrNull(),
|
||||
}));
|
||||
};
|
||||
return {
|
||||
doFieldsNeedTracks,
|
||||
canSkipTracks: () => {
|
||||
if (hasAudioTrackHandlers || hasVideoTrackHandlers) {
|
||||
return false;
|
||||
}
|
||||
return !doFieldsNeedTracks();
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.makeCanSkipTracksState = makeCanSkipTracksState;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import type { Reader } from '../readers/reader';
|
||||
export declare const currentReader: (initialReader: Reader) => {
|
||||
getCurrent: () => Reader;
|
||||
setCurrent: (newReader: Reader) => void;
|
||||
};
|
||||
export type CurrentReader = ReturnType<typeof currentReader>;
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.currentReader = void 0;
|
||||
const currentReader = (initialReader) => {
|
||||
let current = initialReader;
|
||||
return {
|
||||
getCurrent: () => current,
|
||||
setCurrent: (newReader) => {
|
||||
current = newReader;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.currentReader = currentReader;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { AllOptions, ParseMediaFields } from '../fields';
|
||||
export declare const emittedState: () => AllOptions<ParseMediaFields>;
|
||||
Generated
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.emittedState = void 0;
|
||||
const emittedState = () => {
|
||||
const emittedFields = {
|
||||
audioCodec: false,
|
||||
container: false,
|
||||
dimensions: false,
|
||||
durationInSeconds: false,
|
||||
fps: false,
|
||||
internalStats: false,
|
||||
isHdr: false,
|
||||
location: false,
|
||||
metadata: false,
|
||||
mimeType: false,
|
||||
name: false,
|
||||
rotation: false,
|
||||
size: false,
|
||||
slowStructure: false,
|
||||
tracks: false,
|
||||
videoCodec: false,
|
||||
unrotatedDimensions: false,
|
||||
slowDurationInSeconds: false,
|
||||
slowFps: false,
|
||||
slowKeyframes: false,
|
||||
slowNumberOfFrames: false,
|
||||
keyframes: false,
|
||||
images: false,
|
||||
numberOfAudioChannels: false,
|
||||
sampleRate: false,
|
||||
slowAudioBitrate: false,
|
||||
slowVideoBitrate: false,
|
||||
m3uStreams: false,
|
||||
};
|
||||
return emittedFields;
|
||||
};
|
||||
exports.emittedState = emittedState;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
export declare const flacState: () => {
|
||||
setBlockingBitStrategy: (strategy: number) => void;
|
||||
getBlockingBitStrategy: () => number | undefined;
|
||||
audioSamples: {
|
||||
addSample: (audioSampleOffset: import("./audio-sample-map").AudioSampleOffset) => void;
|
||||
getSamples: () => import("./audio-sample-map").AudioSampleOffset[];
|
||||
setFromSeekingHints: (newMap: import("./audio-sample-map").AudioSampleOffset[]) => void;
|
||||
};
|
||||
};
|
||||
export type FlacState = ReturnType<typeof flacState>;
|
||||
Generated
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.flacState = void 0;
|
||||
const audio_sample_map_1 = require("./audio-sample-map");
|
||||
const flacState = () => {
|
||||
let blockingBitStrategy;
|
||||
const audioSamples = (0, audio_sample_map_1.audioSampleMapState)();
|
||||
return {
|
||||
setBlockingBitStrategy: (strategy) => {
|
||||
blockingBitStrategy = strategy;
|
||||
},
|
||||
getBlockingBitStrategy: () => blockingBitStrategy,
|
||||
audioSamples,
|
||||
};
|
||||
};
|
||||
exports.flacState = flacState;
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
import type { Options, ParseMediaFields } from '../fields';
|
||||
import type { MediaParserTrack } from '../get-tracks';
|
||||
import type { MediaParserLogLevel } from '../log';
|
||||
import type { ParseMediaSrc } from '../options';
|
||||
import type { CanSkipTracksState } from './can-skip-tracks';
|
||||
export declare const makeTracksSectionState: (canSkipTracksState: CanSkipTracksState, src: ParseMediaSrc) => {
|
||||
hasAllTracks: () => boolean;
|
||||
getIsDone: () => boolean;
|
||||
setIsDone: (logLevel: MediaParserLogLevel) => void;
|
||||
addTrack: (track: MediaParserTrack) => void;
|
||||
getTracks: () => MediaParserTrack[];
|
||||
ensureHasTracksAtEnd: (fields: Options<ParseMediaFields>) => void;
|
||||
};
|
||||
export type TracksState = ReturnType<typeof makeTracksSectionState>;
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeTracksSectionState = void 0;
|
||||
const log_1 = require("../log");
|
||||
const makeTracksSectionState = (canSkipTracksState, src) => {
|
||||
const tracks = [];
|
||||
let doneWithTracks = false;
|
||||
return {
|
||||
hasAllTracks: () => doneWithTracks,
|
||||
getIsDone: () => doneWithTracks,
|
||||
setIsDone: (logLevel) => {
|
||||
if (doneWithTracks) {
|
||||
throw new Error('Error in Media Parser: Tracks have already been parsed');
|
||||
}
|
||||
log_1.Log.verbose(logLevel, 'All tracks have been parsed');
|
||||
doneWithTracks = true;
|
||||
},
|
||||
addTrack: (track) => {
|
||||
tracks.push(track);
|
||||
},
|
||||
getTracks: () => {
|
||||
return tracks;
|
||||
},
|
||||
ensureHasTracksAtEnd: (fields) => {
|
||||
if (canSkipTracksState.canSkipTracks()) {
|
||||
return;
|
||||
}
|
||||
if (!fields.tracks) {
|
||||
return;
|
||||
}
|
||||
if (!doneWithTracks) {
|
||||
throw new Error('Error in Media Parser: End of parsing of ' +
|
||||
src +
|
||||
' has been reached, but no tracks have been found ');
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.makeTracksSectionState = makeTracksSectionState;
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
export type MediaParserEmbeddedImage = {
|
||||
description: string | null;
|
||||
mimeType: string | null;
|
||||
data: Uint8Array;
|
||||
};
|
||||
export declare const imagesState: () => {
|
||||
images: MediaParserEmbeddedImage[];
|
||||
addImage: (image: MediaParserEmbeddedImage) => void;
|
||||
};
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.imagesState = void 0;
|
||||
const imagesState = () => {
|
||||
const images = [];
|
||||
const addImage = (image) => {
|
||||
images.push(image);
|
||||
};
|
||||
return {
|
||||
images,
|
||||
addImage,
|
||||
};
|
||||
};
|
||||
exports.imagesState = imagesState;
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
import type { SamplePosition } from '../../get-sample-positions';
|
||||
import type { ParserState } from '../parser-state';
|
||||
type TrackIdAndSamplePositions = {
|
||||
trackId: number;
|
||||
samplePositions: SamplePosition[];
|
||||
};
|
||||
export declare const calculateSamplePositions: ({ state, mediaSectionStart, trackIds, }: {
|
||||
state: ParserState;
|
||||
mediaSectionStart: number;
|
||||
trackIds: number[];
|
||||
}) => TrackIdAndSamplePositions[];
|
||||
export declare const cachedSamplePositionsState: () => {
|
||||
getSamples: (mdatStart: number) => TrackIdAndSamplePositions[] | null;
|
||||
setSamples: (mdatStart: number, samples: TrackIdAndSamplePositions[]) => void;
|
||||
setCurrentSampleIndex: (mdatStart: number, trackId: number, index: number) => void;
|
||||
getCurrentSampleIndices: (mdatStart: number) => Record<number, number>;
|
||||
updateAfterSeek: (seekedByte: number) => void;
|
||||
};
|
||||
type Lowest = {
|
||||
samplePosition: SamplePosition;
|
||||
trackId: number;
|
||||
index: number;
|
||||
};
|
||||
export declare const getSampleWithLowestDts: (samplePositions: TrackIdAndSamplePositions[], currentSampleIndexMap: Record<number, number>) => Lowest[];
|
||||
export {};
|
||||
Generated
Vendored
+137
@@ -0,0 +1,137 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getSampleWithLowestDts = exports.cachedSamplePositionsState = exports.calculateSamplePositions = void 0;
|
||||
const are_samples_complete_1 = require("../../containers/iso-base-media/are-samples-complete");
|
||||
const get_sample_positions_from_track_1 = require("../../containers/iso-base-media/get-sample-positions-from-track");
|
||||
const traversal_1 = require("../../containers/iso-base-media/traversal");
|
||||
const get_tracks_1 = require("../../get-tracks");
|
||||
const log_1 = require("../../log");
|
||||
const precomputed_tfra_1 = require("./precomputed-tfra");
|
||||
const calculateSamplePositions = ({ state, mediaSectionStart, trackIds, }) => {
|
||||
var _a, _b;
|
||||
const tracks = (0, get_tracks_1.getTracks)(state, true);
|
||||
const moofBoxes = (0, traversal_1.getMoofBoxes)(state.structure.getIsoStructure().boxes);
|
||||
const tfraBoxes = (0, precomputed_tfra_1.deduplicateTfraBoxesByOffset)([
|
||||
...state.iso.tfra.getTfraBoxes(),
|
||||
...(0, traversal_1.getTfraBoxes)(state.structure.getIsoStructure().boxes),
|
||||
]);
|
||||
const moofComplete = (0, are_samples_complete_1.areSamplesComplete)({ moofBoxes, tfraBoxes });
|
||||
const relevantMoofBox = moofBoxes.find((moofBox) => moofBox.offset + moofBox.size + 8 === mediaSectionStart);
|
||||
if (moofBoxes.length > 0 && !relevantMoofBox) {
|
||||
throw new Error('No relevant moof box found');
|
||||
}
|
||||
const moov = (0, traversal_1.getMoovBoxFromState)({
|
||||
structureState: state.structure,
|
||||
isoState: state.iso,
|
||||
mp4HeaderSegment: (_b = (_a = state.m3uPlaylistContext) === null || _a === void 0 ? void 0 : _a.mp4HeaderSegment) !== null && _b !== void 0 ? _b : null,
|
||||
mayUsePrecomputed: true,
|
||||
});
|
||||
if (!moov) {
|
||||
throw new Error('No moov box found');
|
||||
}
|
||||
const trackIdAndSamplePositions = [];
|
||||
for (const track of tracks) {
|
||||
const trakBox = (0, traversal_1.getTrakBoxByTrackId)(moov, track.trackId);
|
||||
if (!trackIds.includes(track.trackId)) {
|
||||
log_1.Log.verbose(state.logLevel, 'Skipping calculating sample positions for track', track.trackId);
|
||||
continue;
|
||||
}
|
||||
if (!trakBox) {
|
||||
throw new Error('No trak box found');
|
||||
}
|
||||
const { samplePositions } = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)({
|
||||
trakBox,
|
||||
moofBoxes: relevantMoofBox ? [relevantMoofBox] : [],
|
||||
moofComplete,
|
||||
trexBoxes: (0, traversal_1.getTrexBoxes)(moov),
|
||||
});
|
||||
trackIdAndSamplePositions.push({
|
||||
trackId: track.trackId,
|
||||
samplePositions,
|
||||
});
|
||||
}
|
||||
return trackIdAndSamplePositions;
|
||||
};
|
||||
exports.calculateSamplePositions = calculateSamplePositions;
|
||||
const updateSampleIndicesAfterSeek = ({ samplePositionsForMdatStart, seekedByte, }) => {
|
||||
const currentSampleIndices = {};
|
||||
const keys = Object.keys(samplePositionsForMdatStart).map(Number).sort();
|
||||
const mdat = keys.find((key) => seekedByte >= key);
|
||||
if (!mdat) {
|
||||
return currentSampleIndices;
|
||||
}
|
||||
const samplePositions = samplePositionsForMdatStart[mdat];
|
||||
if (!samplePositions) {
|
||||
return currentSampleIndices;
|
||||
}
|
||||
for (const track of samplePositions) {
|
||||
const currentSampleIndex = track.samplePositions.findIndex((sample) => sample.offset >= seekedByte);
|
||||
if (!currentSampleIndices[mdat]) {
|
||||
currentSampleIndices[mdat] = {};
|
||||
}
|
||||
if (!currentSampleIndices[mdat][track.trackId]) {
|
||||
currentSampleIndices[mdat][track.trackId] = 0;
|
||||
}
|
||||
if (currentSampleIndex === -1) {
|
||||
currentSampleIndices[mdat][track.trackId] = track.samplePositions.length;
|
||||
}
|
||||
else {
|
||||
currentSampleIndices[mdat][track.trackId] = currentSampleIndex;
|
||||
}
|
||||
}
|
||||
return currentSampleIndices;
|
||||
};
|
||||
const cachedSamplePositionsState = () => {
|
||||
// offset -> sample positions
|
||||
const samplePositionsForMdatStart = {};
|
||||
let currentSampleIndex = {};
|
||||
return {
|
||||
getSamples: (mdatStart) => {
|
||||
var _a;
|
||||
return (_a = samplePositionsForMdatStart[mdatStart]) !== null && _a !== void 0 ? _a : null;
|
||||
},
|
||||
setSamples: (mdatStart, samples) => {
|
||||
samplePositionsForMdatStart[mdatStart] = samples;
|
||||
},
|
||||
setCurrentSampleIndex: (mdatStart, trackId, index) => {
|
||||
if (!currentSampleIndex[mdatStart]) {
|
||||
currentSampleIndex[mdatStart] = {};
|
||||
}
|
||||
if (!currentSampleIndex[mdatStart][trackId]) {
|
||||
currentSampleIndex[mdatStart][trackId] = 0;
|
||||
}
|
||||
currentSampleIndex[mdatStart][trackId] = index;
|
||||
},
|
||||
getCurrentSampleIndices: (mdatStart) => {
|
||||
var _a;
|
||||
return (_a = currentSampleIndex[mdatStart]) !== null && _a !== void 0 ? _a : {};
|
||||
},
|
||||
updateAfterSeek: (seekedByte) => {
|
||||
currentSampleIndex = updateSampleIndicesAfterSeek({
|
||||
samplePositionsForMdatStart,
|
||||
seekedByte,
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.cachedSamplePositionsState = cachedSamplePositionsState;
|
||||
const getSampleWithLowestDts = (samplePositions, currentSampleIndexMap) => {
|
||||
var _a;
|
||||
const lowestDts = [];
|
||||
for (const track of samplePositions) {
|
||||
const currentSampleIndex = (_a = currentSampleIndexMap[track.trackId]) !== null && _a !== void 0 ? _a : 0;
|
||||
const currentSample = track.samplePositions[currentSampleIndex];
|
||||
if (currentSample &&
|
||||
(lowestDts.length === 0 ||
|
||||
currentSample.decodingTimestamp <=
|
||||
lowestDts[0].samplePosition.decodingTimestamp)) {
|
||||
lowestDts.push({
|
||||
samplePosition: currentSample,
|
||||
trackId: track.trackId,
|
||||
index: currentSampleIndex,
|
||||
});
|
||||
}
|
||||
}
|
||||
return lowestDts;
|
||||
};
|
||||
exports.getSampleWithLowestDts = getSampleWithLowestDts;
|
||||
Generated
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
import type { MediaParserController } from '../../controller/media-parser-controller';
|
||||
import type { PrefetchCache } from '../../fetch';
|
||||
import type { MediaParserLogLevel } from '../../log';
|
||||
import type { ParseMediaSrc } from '../../options';
|
||||
import type { MediaParserReaderInterface } from '../../readers/reader';
|
||||
export declare const isoBaseMediaState: ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }: {
|
||||
contentLength: number;
|
||||
controller: MediaParserController;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
src: ParseMediaSrc;
|
||||
logLevel: MediaParserLogLevel;
|
||||
prefetchCache: PrefetchCache;
|
||||
}) => {
|
||||
flatSamples: {
|
||||
getSamples: (mdatStart: number) => {
|
||||
trackId: number;
|
||||
samplePositions: import("../../get-sample-positions").SamplePosition[];
|
||||
}[] | null;
|
||||
setSamples: (mdatStart: number, samples: {
|
||||
trackId: number;
|
||||
samplePositions: import("../../get-sample-positions").SamplePosition[];
|
||||
}[]) => void;
|
||||
setCurrentSampleIndex: (mdatStart: number, trackId: number, index: number) => void;
|
||||
getCurrentSampleIndices: (mdatStart: number) => Record<number, number>;
|
||||
updateAfterSeek: (seekedByte: number) => void;
|
||||
};
|
||||
moov: {
|
||||
setMoovBox: (moov: {
|
||||
moovBox: import("../../containers/iso-base-media/moov/moov").MoovBox;
|
||||
precomputed: boolean;
|
||||
}) => void;
|
||||
getMoovBoxAndPrecomputed: () => {
|
||||
moovBox: import("../../containers/iso-base-media/moov/moov").MoovBox;
|
||||
precomputed: boolean;
|
||||
} | null;
|
||||
};
|
||||
mfra: {
|
||||
triggerLoad: () => Promise<import("../../containers/iso-base-media/base-media-box").IsoBaseMediaBox[] | null>;
|
||||
getIfAlreadyLoaded: () => import("../../containers/iso-base-media/base-media-box").IsoBaseMediaBox[] | null;
|
||||
setFromSeekingHints: (hints: import("../../seeking-hints").IsoBaseMediaSeekingHints) => void;
|
||||
};
|
||||
moof: {
|
||||
getMoofBoxes: () => import("./precomputed-moof").MoofBox[];
|
||||
setMoofBoxes: (boxes: import("./precomputed-moof").MoofBox[]) => void;
|
||||
};
|
||||
tfra: {
|
||||
getTfraBoxes: () => import("../../containers/iso-base-media/mfra/tfra").TfraBox[];
|
||||
setTfraBoxes: (boxes: import("../../containers/iso-base-media/mfra/tfra").TfraBox[]) => void;
|
||||
};
|
||||
movieTimeScale: {
|
||||
getTrackTimescale: () => number | null;
|
||||
setTrackTimescale: (timescale: number) => void;
|
||||
};
|
||||
};
|
||||
export type IsoBaseMediaState = ReturnType<typeof isoBaseMediaState>;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isoBaseMediaState = void 0;
|
||||
const cached_sample_positions_1 = require("./cached-sample-positions");
|
||||
const lazy_mfra_load_1 = require("./lazy-mfra-load");
|
||||
const moov_box_1 = require("./moov-box");
|
||||
const precomputed_moof_1 = require("./precomputed-moof");
|
||||
const precomputed_tfra_1 = require("./precomputed-tfra");
|
||||
const timescale_state_1 = require("./timescale-state");
|
||||
const isoBaseMediaState = ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }) => {
|
||||
return {
|
||||
flatSamples: (0, cached_sample_positions_1.cachedSamplePositionsState)(),
|
||||
moov: (0, moov_box_1.moovState)(),
|
||||
mfra: (0, lazy_mfra_load_1.lazyMfraLoad)({
|
||||
contentLength,
|
||||
controller,
|
||||
readerInterface,
|
||||
src,
|
||||
logLevel,
|
||||
prefetchCache,
|
||||
}),
|
||||
moof: (0, precomputed_moof_1.precomputedMoofState)(),
|
||||
tfra: (0, precomputed_tfra_1.precomputedTfraState)(),
|
||||
movieTimeScale: (0, timescale_state_1.movieTimeScaleState)(),
|
||||
};
|
||||
};
|
||||
exports.isoBaseMediaState = isoBaseMediaState;
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
import type { IsoBaseMediaBox } from '../../containers/iso-base-media/base-media-box';
|
||||
export declare const getLastMoofBox: (boxes: IsoBaseMediaBox[]) => number | null | undefined;
|
||||
export declare const getMaxFirstMoofOffset: (boxes: IsoBaseMediaBox[]) => number;
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMaxFirstMoofOffset = exports.getLastMoofBox = void 0;
|
||||
const truthy_1 = require("../../truthy");
|
||||
const getLastMoofBox = (boxes) => {
|
||||
if (boxes) {
|
||||
const tfras = boxes.filter((b) => b.type === 'tfra-box');
|
||||
const lastMoofOffsets = tfras.map((f) => {
|
||||
if (f.entries.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
return f.entries[f.entries.length - 1].moofOffset;
|
||||
});
|
||||
if (lastMoofOffsets.length > 0) {
|
||||
const maxOffset = Math.max(...lastMoofOffsets.filter(truthy_1.truthy));
|
||||
return maxOffset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
exports.getLastMoofBox = getLastMoofBox;
|
||||
const getMaxFirstMoofOffset = (boxes) => {
|
||||
const tfras = boxes.filter((b) => b.type === 'tfra-box');
|
||||
const firstMoofOffsets = tfras.map((f) => {
|
||||
return f.entries[0].moofOffset;
|
||||
});
|
||||
return Math.max(...firstMoofOffsets.filter(truthy_1.truthy));
|
||||
};
|
||||
exports.getMaxFirstMoofOffset = getMaxFirstMoofOffset;
|
||||
Generated
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
import type { IsoBaseMediaBox } from '../../containers/iso-base-media/base-media-box';
|
||||
import type { MediaParserController } from '../../controller/media-parser-controller';
|
||||
import type { PrefetchCache } from '../../fetch';
|
||||
import { type MediaParserLogLevel } from '../../log';
|
||||
import type { ParseMediaSrc } from '../../options';
|
||||
import type { MediaParserReaderInterface } from '../../readers/reader';
|
||||
import type { IsoBaseMediaSeekingHints } from '../../seeking-hints';
|
||||
export declare const lazyMfraLoad: ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }: {
|
||||
contentLength: number;
|
||||
controller: MediaParserController;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
src: ParseMediaSrc;
|
||||
logLevel: MediaParserLogLevel;
|
||||
prefetchCache: PrefetchCache;
|
||||
}) => {
|
||||
triggerLoad: () => Promise<IsoBaseMediaBox[] | null>;
|
||||
getIfAlreadyLoaded: () => IsoBaseMediaBox[] | null;
|
||||
setFromSeekingHints: (hints: IsoBaseMediaSeekingHints) => void;
|
||||
};
|
||||
Generated
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.lazyMfraLoad = void 0;
|
||||
const get_mfra_seeking_box_1 = require("../../containers/iso-base-media/get-mfra-seeking-box");
|
||||
const log_1 = require("../../log");
|
||||
const lazyMfraLoad = ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }) => {
|
||||
let prom = null;
|
||||
let result = null;
|
||||
const triggerLoad = () => {
|
||||
if (prom) {
|
||||
return prom;
|
||||
}
|
||||
log_1.Log.verbose(logLevel, 'Moof box found, trying to lazy load mfra');
|
||||
prom = (0, get_mfra_seeking_box_1.getMfraSeekingBox)({
|
||||
contentLength,
|
||||
controller,
|
||||
readerInterface,
|
||||
src,
|
||||
logLevel,
|
||||
prefetchCache,
|
||||
}).then((boxes) => {
|
||||
log_1.Log.verbose(logLevel, boxes ? 'Lazily found mfra atom.' : 'No mfra atom found.');
|
||||
result = boxes;
|
||||
return boxes;
|
||||
});
|
||||
return prom;
|
||||
};
|
||||
const getIfAlreadyLoaded = () => {
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const setFromSeekingHints = (hints) => {
|
||||
result = hints.mfraAlreadyLoaded;
|
||||
};
|
||||
return {
|
||||
triggerLoad,
|
||||
getIfAlreadyLoaded,
|
||||
setFromSeekingHints,
|
||||
};
|
||||
};
|
||||
exports.lazyMfraLoad = lazyMfraLoad;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type { MoovBox } from '../../containers/iso-base-media/moov/moov';
|
||||
type MoovBoxAndPrecomputed = {
|
||||
moovBox: MoovBox;
|
||||
precomputed: boolean;
|
||||
};
|
||||
export declare const moovState: () => {
|
||||
setMoovBox: (moov: MoovBoxAndPrecomputed) => void;
|
||||
getMoovBoxAndPrecomputed: () => MoovBoxAndPrecomputed | null;
|
||||
};
|
||||
export {};
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.moovState = void 0;
|
||||
const moovState = () => {
|
||||
let moovBox = null;
|
||||
return {
|
||||
setMoovBox: (moov) => {
|
||||
moovBox = moov;
|
||||
},
|
||||
getMoovBoxAndPrecomputed: () => moovBox,
|
||||
};
|
||||
};
|
||||
exports.moovState = moovState;
|
||||
Generated
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
import type { IsoBaseMediaBox } from '../../containers/iso-base-media/base-media-box';
|
||||
export type MoofBox = {
|
||||
offset: number;
|
||||
size: number;
|
||||
trafBoxes: IsoBaseMediaBox[];
|
||||
};
|
||||
export declare const precomputedMoofState: () => {
|
||||
getMoofBoxes: () => MoofBox[];
|
||||
setMoofBoxes: (boxes: MoofBox[]) => void;
|
||||
};
|
||||
export declare const toMoofBox: (box: IsoBaseMediaBox) => MoofBox;
|
||||
export declare const deduplicateMoofBoxesByOffset: (moofBoxes: MoofBox[]) => MoofBox[];
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.deduplicateMoofBoxesByOffset = exports.toMoofBox = exports.precomputedMoofState = void 0;
|
||||
// Note: May be duplicated!
|
||||
const precomputedMoofState = () => {
|
||||
let moofBoxes = [];
|
||||
return {
|
||||
getMoofBoxes: () => moofBoxes,
|
||||
setMoofBoxes: (boxes) => {
|
||||
moofBoxes = boxes;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.precomputedMoofState = precomputedMoofState;
|
||||
const toMoofBox = (box) => {
|
||||
if (box.type !== 'regular-box') {
|
||||
throw new Error('expected regular bpx');
|
||||
}
|
||||
return {
|
||||
offset: box.offset,
|
||||
trafBoxes: box.children.filter((c) => c.type === 'regular-box' && c.boxType === 'traf'),
|
||||
size: box.boxSize,
|
||||
};
|
||||
};
|
||||
exports.toMoofBox = toMoofBox;
|
||||
const deduplicateMoofBoxesByOffset = (moofBoxes) => {
|
||||
return moofBoxes.filter((m, i, arr) => i === arr.findIndex((t) => t.offset === m.offset));
|
||||
};
|
||||
exports.deduplicateMoofBoxesByOffset = deduplicateMoofBoxesByOffset;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import type { TfraBox } from '../../containers/iso-base-media/mfra/tfra';
|
||||
export declare const precomputedTfraState: () => {
|
||||
getTfraBoxes: () => TfraBox[];
|
||||
setTfraBoxes: (boxes: TfraBox[]) => void;
|
||||
};
|
||||
export declare const deduplicateTfraBoxesByOffset: (tfraBoxes: TfraBox[]) => TfraBox[];
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.deduplicateTfraBoxesByOffset = exports.precomputedTfraState = void 0;
|
||||
const precomputedTfraState = () => {
|
||||
let tfraBoxes = [];
|
||||
return {
|
||||
getTfraBoxes: () => tfraBoxes,
|
||||
setTfraBoxes: (boxes) => {
|
||||
tfraBoxes = boxes;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.precomputedTfraState = precomputedTfraState;
|
||||
const deduplicateTfraBoxesByOffset = (tfraBoxes) => {
|
||||
return tfraBoxes.filter((m, i, arr) => i === arr.findIndex((t) => t.offset === m.offset));
|
||||
};
|
||||
exports.deduplicateTfraBoxesByOffset = deduplicateTfraBoxesByOffset;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
export declare const movieTimeScaleState: () => {
|
||||
getTrackTimescale: () => number | null;
|
||||
setTrackTimescale: (timescale: number) => void;
|
||||
};
|
||||
export type MovieTimeScaleState = ReturnType<typeof movieTimeScaleState>;
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.movieTimeScaleState = void 0;
|
||||
const movieTimeScaleState = () => {
|
||||
let trackTimescale = null;
|
||||
return {
|
||||
getTrackTimescale: () => trackTimescale,
|
||||
setTrackTimescale: (timescale) => {
|
||||
trackTimescale = timescale;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.movieTimeScaleState = movieTimeScaleState;
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import type { MediaParserKeyframe } from '../options';
|
||||
export declare const keyframesState: () => {
|
||||
addKeyframe: (keyframe: MediaParserKeyframe) => void;
|
||||
getKeyframes: () => MediaParserKeyframe[];
|
||||
setFromSeekingHints: (keyframesFromHints: MediaParserKeyframe[]) => void;
|
||||
};
|
||||
export type KeyframesState = ReturnType<typeof keyframesState>;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.keyframesState = void 0;
|
||||
const keyframesState = () => {
|
||||
const keyframes = [];
|
||||
const addKeyframe = (keyframe) => {
|
||||
if (keyframes.find((k) => k.positionInBytes === keyframe.positionInBytes)) {
|
||||
return;
|
||||
}
|
||||
keyframes.push(keyframe);
|
||||
};
|
||||
const getKeyframes = () => {
|
||||
keyframes.sort((a, b) => a.positionInBytes - b.positionInBytes);
|
||||
return keyframes;
|
||||
};
|
||||
const setFromSeekingHints = (keyframesFromHints) => {
|
||||
for (const keyframe of keyframesFromHints) {
|
||||
addKeyframe(keyframe);
|
||||
}
|
||||
};
|
||||
return {
|
||||
addKeyframe,
|
||||
getKeyframes,
|
||||
setFromSeekingHints,
|
||||
};
|
||||
};
|
||||
exports.keyframesState = keyframesState;
|
||||
Generated
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
import type { M3uAssociatedPlaylist, M3uStream } from '../containers/m3u/get-streams';
|
||||
import type { MediaParserLogLevel } from '../log';
|
||||
import type { IsoBaseMediaStructure } from '../parse-result';
|
||||
import type { MediaParserOnAudioSample, MediaParserOnVideoSample } from '../webcodec-sample-types';
|
||||
export type M3uStreamOrInitialUrl = {
|
||||
type: 'selected-stream';
|
||||
stream: M3uStream;
|
||||
} | {
|
||||
type: 'initial-url';
|
||||
url: string;
|
||||
};
|
||||
export type M3uRun = {
|
||||
continue: () => Promise<M3uRun | null>;
|
||||
abort: () => void;
|
||||
};
|
||||
type M3uSeek = {
|
||||
targetTime: number;
|
||||
};
|
||||
export declare const m3uState: (logLevel: MediaParserLogLevel) => {
|
||||
setSelectedMainPlaylist: (stream: M3uStreamOrInitialUrl) => void;
|
||||
getSelectedMainPlaylist: () => M3uStreamOrInitialUrl | null;
|
||||
setHasEmittedVideoTrack: (src: string, callback: MediaParserOnVideoSample | null) => void;
|
||||
hasEmittedVideoTrack: (src: string) => false | MediaParserOnVideoSample | null;
|
||||
setHasEmittedAudioTrack: (src: string, callback: MediaParserOnAudioSample | null) => void;
|
||||
hasEmittedAudioTrack: (src: string) => false | MediaParserOnAudioSample | null;
|
||||
setHasEmittedDoneWithTracks: (src: string) => void;
|
||||
hasEmittedDoneWithTracks: (src: string) => boolean;
|
||||
setReadyToIterateOverM3u: () => void;
|
||||
isReadyToIterateOverM3u: () => boolean;
|
||||
setAllChunksProcessed: (src: string) => void;
|
||||
clearAllChunksProcessed: () => void;
|
||||
getAllChunksProcessedForPlaylist: (src: string) => boolean;
|
||||
getAllChunksProcessedOverall: () => boolean;
|
||||
setHasFinishedManifest: () => void;
|
||||
hasFinishedManifest: () => boolean;
|
||||
setM3uStreamRun: (playlistUrl: string, run: M3uRun | null) => void;
|
||||
setTracksDone: (playlistUrl: string) => boolean;
|
||||
getTrackDone: (playlistUrl: string) => boolean;
|
||||
clearTracksDone: () => void;
|
||||
getM3uStreamRun: (playlistUrl: string) => M3uRun;
|
||||
abortM3UStreamRuns: () => void;
|
||||
setAssociatedPlaylists: (playlists: M3uAssociatedPlaylist[]) => void;
|
||||
getAssociatedPlaylists: () => M3uAssociatedPlaylist[] | null;
|
||||
getSelectedPlaylists: () => string[];
|
||||
sampleSorter: {
|
||||
clearSamples: () => void;
|
||||
addToStreamWithTrack: (src: string) => void;
|
||||
addVideoStreamToConsider: (src: string, callback: MediaParserOnVideoSample) => void;
|
||||
addAudioStreamToConsider: (src: string, callback: MediaParserOnAudioSample) => void;
|
||||
hasAudioStreamToConsider: (src: string) => boolean;
|
||||
hasVideoStreamToConsider: (src: string) => boolean;
|
||||
addAudioSample: (src: string, sample: import("../webcodec-sample-types").MediaParserAudioSample) => Promise<void>;
|
||||
addVideoSample: (src: string, sample: import("../webcodec-sample-types").MediaParserVideoSample) => Promise<void>;
|
||||
getNextStreamToRun: (streams: string[]) => string;
|
||||
};
|
||||
setMp4HeaderSegment: (playlistUrl: string, structure: IsoBaseMediaStructure) => void;
|
||||
getMp4HeaderSegment: (playlistUrl: string) => IsoBaseMediaStructure;
|
||||
setSeekToSecondsToProcess: (playlistUrl: string, m3uSeek: M3uSeek | null) => void;
|
||||
getSeekToSecondsToProcess: (playlistUrl: string) => M3uSeek | null;
|
||||
setNextSeekShouldSubtractChunks: (playlistUrl: string, chunks: number) => void;
|
||||
getNextSeekShouldSubtractChunks: (playlistUrl: string) => number;
|
||||
};
|
||||
export type M3uState = ReturnType<typeof m3uState>;
|
||||
export {};
|
||||
Generated
Vendored
+144
@@ -0,0 +1,144 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.m3uState = void 0;
|
||||
const sample_sorter_1 = require("../containers/m3u/sample-sorter");
|
||||
const log_1 = require("../log");
|
||||
const m3uState = (logLevel) => {
|
||||
let selectedMainPlaylist = null;
|
||||
let associatedPlaylists = null;
|
||||
const hasEmittedVideoTrack = {};
|
||||
const hasEmittedAudioTrack = {};
|
||||
const hasEmittedDoneWithTracks = {};
|
||||
let hasFinishedManifest = false;
|
||||
const seekToSecondsToProcess = {};
|
||||
const nextSeekShouldSubtractChunks = {};
|
||||
let readyToIterateOverM3u = false;
|
||||
const allChunksProcessed = {};
|
||||
const m3uStreamRuns = {};
|
||||
const tracksDone = {};
|
||||
const getMainPlaylistUrl = () => {
|
||||
if (!selectedMainPlaylist) {
|
||||
throw new Error('No main playlist selected');
|
||||
}
|
||||
const playlistUrl = selectedMainPlaylist.type === 'initial-url'
|
||||
? selectedMainPlaylist.url
|
||||
: selectedMainPlaylist.stream.src;
|
||||
return playlistUrl;
|
||||
};
|
||||
const getSelectedPlaylists = () => {
|
||||
return [
|
||||
getMainPlaylistUrl(),
|
||||
...(associatedPlaylists !== null && associatedPlaylists !== void 0 ? associatedPlaylists : []).map((p) => p.src),
|
||||
];
|
||||
};
|
||||
const getAllChunksProcessedForPlaylist = (src) => allChunksProcessed[src];
|
||||
const mp4HeaderSegments = {};
|
||||
const setMp4HeaderSegment = (playlistUrl, structure) => {
|
||||
mp4HeaderSegments[playlistUrl] = structure;
|
||||
};
|
||||
const getMp4HeaderSegment = (playlistUrl) => {
|
||||
return mp4HeaderSegments[playlistUrl];
|
||||
};
|
||||
return {
|
||||
setSelectedMainPlaylist: (stream) => {
|
||||
selectedMainPlaylist = stream;
|
||||
},
|
||||
getSelectedMainPlaylist: () => selectedMainPlaylist,
|
||||
setHasEmittedVideoTrack: (src, callback) => {
|
||||
hasEmittedVideoTrack[src] = callback;
|
||||
},
|
||||
hasEmittedVideoTrack: (src) => {
|
||||
const value = hasEmittedVideoTrack[src];
|
||||
if (value === undefined) {
|
||||
return false;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
setHasEmittedAudioTrack: (src, callback) => {
|
||||
hasEmittedAudioTrack[src] = callback;
|
||||
},
|
||||
hasEmittedAudioTrack: (src) => {
|
||||
const value = hasEmittedAudioTrack[src];
|
||||
if (value === undefined) {
|
||||
return false;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
setHasEmittedDoneWithTracks: (src) => {
|
||||
hasEmittedDoneWithTracks[src] = true;
|
||||
},
|
||||
hasEmittedDoneWithTracks: (src) => hasEmittedDoneWithTracks[src] !== undefined,
|
||||
setReadyToIterateOverM3u: () => {
|
||||
readyToIterateOverM3u = true;
|
||||
},
|
||||
isReadyToIterateOverM3u: () => readyToIterateOverM3u,
|
||||
setAllChunksProcessed: (src) => {
|
||||
allChunksProcessed[src] = true;
|
||||
},
|
||||
clearAllChunksProcessed: () => {
|
||||
Object.keys(allChunksProcessed).forEach((key) => {
|
||||
delete allChunksProcessed[key];
|
||||
});
|
||||
},
|
||||
getAllChunksProcessedForPlaylist,
|
||||
getAllChunksProcessedOverall: () => {
|
||||
if (!selectedMainPlaylist) {
|
||||
return false;
|
||||
}
|
||||
const selectedPlaylists = getSelectedPlaylists();
|
||||
return selectedPlaylists.every((url) => allChunksProcessed[url]);
|
||||
},
|
||||
setHasFinishedManifest: () => {
|
||||
hasFinishedManifest = true;
|
||||
},
|
||||
hasFinishedManifest: () => hasFinishedManifest,
|
||||
setM3uStreamRun: (playlistUrl, run) => {
|
||||
if (!run) {
|
||||
delete m3uStreamRuns[playlistUrl];
|
||||
return;
|
||||
}
|
||||
m3uStreamRuns[playlistUrl] = run;
|
||||
},
|
||||
setTracksDone: (playlistUrl) => {
|
||||
tracksDone[playlistUrl] = true;
|
||||
const selectedPlaylists = getSelectedPlaylists();
|
||||
return selectedPlaylists.every((url) => tracksDone[url]);
|
||||
},
|
||||
getTrackDone: (playlistUrl) => {
|
||||
return tracksDone[playlistUrl];
|
||||
},
|
||||
clearTracksDone: () => {
|
||||
Object.keys(tracksDone).forEach((key) => {
|
||||
delete tracksDone[key];
|
||||
});
|
||||
},
|
||||
getM3uStreamRun: (playlistUrl) => { var _a; return (_a = m3uStreamRuns[playlistUrl]) !== null && _a !== void 0 ? _a : null; },
|
||||
abortM3UStreamRuns: () => {
|
||||
const values = Object.values(m3uStreamRuns);
|
||||
if (values.length === 0) {
|
||||
return;
|
||||
}
|
||||
log_1.Log.trace(logLevel, `Aborting ${values.length} M3U stream runs`);
|
||||
values.forEach((run) => {
|
||||
run.abort();
|
||||
});
|
||||
},
|
||||
setAssociatedPlaylists: (playlists) => {
|
||||
associatedPlaylists = playlists;
|
||||
},
|
||||
getAssociatedPlaylists: () => associatedPlaylists,
|
||||
getSelectedPlaylists,
|
||||
sampleSorter: (0, sample_sorter_1.sampleSorter)({ logLevel, getAllChunksProcessedForPlaylist }),
|
||||
setMp4HeaderSegment,
|
||||
getMp4HeaderSegment,
|
||||
setSeekToSecondsToProcess: (playlistUrl, m3uSeek) => {
|
||||
seekToSecondsToProcess[playlistUrl] = m3uSeek;
|
||||
},
|
||||
getSeekToSecondsToProcess: (playlistUrl) => { var _a; return (_a = seekToSecondsToProcess[playlistUrl]) !== null && _a !== void 0 ? _a : null; },
|
||||
setNextSeekShouldSubtractChunks: (playlistUrl, chunks) => {
|
||||
nextSeekShouldSubtractChunks[playlistUrl] = chunks;
|
||||
},
|
||||
getNextSeekShouldSubtractChunks: (playlistUrl) => { var _a; return (_a = nextSeekShouldSubtractChunks[playlistUrl]) !== null && _a !== void 0 ? _a : 0; },
|
||||
};
|
||||
};
|
||||
exports.m3uState = m3uState;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
import type { MatroskaCue } from '../../containers/webm/seek/format-cues';
|
||||
import type { MediaParserController } from '../../controller/media-parser-controller';
|
||||
import type { PrefetchCache } from '../../fetch';
|
||||
import type { MediaParserLogLevel } from '../../log';
|
||||
import type { ParseMediaSrc } from '../../options';
|
||||
import type { MediaParserReaderInterface } from '../../readers/reader';
|
||||
import type { WebmSeekingHints } from '../../seeking-hints';
|
||||
export declare const lazyCuesFetch: ({ controller, logLevel, readerInterface, src, prefetchCache, }: {
|
||||
controller: MediaParserController;
|
||||
logLevel: MediaParserLogLevel;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
src: ParseMediaSrc;
|
||||
prefetchCache: PrefetchCache;
|
||||
}) => {
|
||||
triggerLoad: (position: number, segmentOffset: number) => Promise<MatroskaCue[] | null>;
|
||||
getLoadedCues: () => Promise<{
|
||||
cues: MatroskaCue[];
|
||||
segmentOffset: number;
|
||||
} | null>;
|
||||
getIfAlreadyLoaded: () => {
|
||||
cues: MatroskaCue[];
|
||||
segmentOffset: number;
|
||||
} | null;
|
||||
setFromSeekingHints: (hints: WebmSeekingHints) => void;
|
||||
};
|
||||
export type LazyCuesFetch = ReturnType<typeof lazyCuesFetch>;
|
||||
export type LazyCuesLoadedOrNull = Awaited<ReturnType<LazyCuesFetch['getLoadedCues']>>;
|
||||
Generated
Vendored
+85
@@ -0,0 +1,85 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.lazyCuesFetch = void 0;
|
||||
const fetch_web_cues_1 = require("../../containers/webm/seek/fetch-web-cues");
|
||||
const log_1 = require("../../log");
|
||||
const lazyCuesFetch = ({ controller, logLevel, readerInterface, src, prefetchCache, }) => {
|
||||
let prom = null;
|
||||
let sOffset = null;
|
||||
let result = null;
|
||||
const triggerLoad = (position, segmentOffset) => {
|
||||
if (result) {
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
if (prom) {
|
||||
return prom;
|
||||
}
|
||||
if (sOffset && sOffset !== segmentOffset) {
|
||||
throw new Error('Segment offset mismatch');
|
||||
}
|
||||
sOffset = segmentOffset;
|
||||
log_1.Log.verbose(logLevel, 'Cues box found, trying to lazy load cues');
|
||||
prom = (0, fetch_web_cues_1.fetchWebmCues)({
|
||||
controller,
|
||||
logLevel,
|
||||
position,
|
||||
readerInterface,
|
||||
src,
|
||||
prefetchCache,
|
||||
}).then((cues) => {
|
||||
log_1.Log.verbose(logLevel, 'Cues loaded');
|
||||
result = cues;
|
||||
return cues;
|
||||
});
|
||||
return prom;
|
||||
};
|
||||
const getLoadedCues = async () => {
|
||||
if (!prom) {
|
||||
return null;
|
||||
}
|
||||
if (result) {
|
||||
if (!sOffset) {
|
||||
throw new Error('Segment offset not set');
|
||||
}
|
||||
return {
|
||||
cues: result,
|
||||
segmentOffset: sOffset,
|
||||
};
|
||||
}
|
||||
const cues = await prom;
|
||||
if (!cues) {
|
||||
return null;
|
||||
}
|
||||
if (!sOffset) {
|
||||
throw new Error('Segment offset not set');
|
||||
}
|
||||
return {
|
||||
cues,
|
||||
segmentOffset: sOffset,
|
||||
};
|
||||
};
|
||||
const getIfAlreadyLoaded = () => {
|
||||
if (result) {
|
||||
if (sOffset === null) {
|
||||
throw new Error('Segment offset not set');
|
||||
}
|
||||
return {
|
||||
cues: result,
|
||||
segmentOffset: sOffset,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const setFromSeekingHints = (hints) => {
|
||||
var _a, _b, _c, _d;
|
||||
result = (_b = (_a = hints.loadedCues) === null || _a === void 0 ? void 0 : _a.cues) !== null && _b !== void 0 ? _b : null;
|
||||
sOffset = (_d = (_c = hints.loadedCues) === null || _c === void 0 ? void 0 : _c.segmentOffset) !== null && _d !== void 0 ? _d : null;
|
||||
};
|
||||
return {
|
||||
triggerLoad,
|
||||
getLoadedCues,
|
||||
getIfAlreadyLoaded,
|
||||
setFromSeekingHints,
|
||||
};
|
||||
};
|
||||
exports.lazyCuesFetch = lazyCuesFetch;
|
||||
Generated
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
import type { AvcProfileInfo } from '../../containers/avc/parse-avc';
|
||||
import type { OnTrackEntrySegment } from '../../containers/webm/segments';
|
||||
import type { TrackInfo } from '../../containers/webm/segments/track-entry';
|
||||
import type { MediaParserController } from '../../controller/media-parser-controller';
|
||||
import type { PrefetchCache } from '../../fetch';
|
||||
import type { BufferIterator } from '../../iterator/buffer-iterator';
|
||||
import type { MediaParserLogLevel } from '../../log';
|
||||
import type { ParseMediaSrc } from '../../options';
|
||||
import type { MediaParserReaderInterface } from '../../readers/reader';
|
||||
export type SegmentSection = {
|
||||
start: number;
|
||||
size: number;
|
||||
index: number;
|
||||
};
|
||||
export type ClusterSection = {
|
||||
start: number;
|
||||
size: number;
|
||||
segment: number;
|
||||
};
|
||||
export declare const webmState: ({ controller, logLevel, readerInterface, src, prefetchCache, }: {
|
||||
controller: MediaParserController;
|
||||
logLevel: MediaParserLogLevel;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
src: ParseMediaSrc;
|
||||
prefetchCache: PrefetchCache;
|
||||
}) => {
|
||||
cues: {
|
||||
triggerLoad: (position: number, segmentOffset: number) => Promise<import("../../containers/webm/seek/format-cues").MatroskaCue[] | null>;
|
||||
getLoadedCues: () => Promise<{
|
||||
cues: import("../../containers/webm/seek/format-cues").MatroskaCue[];
|
||||
segmentOffset: number;
|
||||
} | null>;
|
||||
getIfAlreadyLoaded: () => {
|
||||
cues: import("../../containers/webm/seek/format-cues").MatroskaCue[];
|
||||
segmentOffset: number;
|
||||
} | null;
|
||||
setFromSeekingHints: (hints: import("../../seeking-hints").WebmSeekingHints) => void;
|
||||
};
|
||||
onTrackEntrySegment: OnTrackEntrySegment;
|
||||
getTrackInfoByNumber: (id: number) => TrackInfo;
|
||||
setTimestampOffset: (byteOffset: number, timestamp: number) => void;
|
||||
getTimestampOffsetForByteOffset: (byteOffset: number) => number | undefined;
|
||||
getTimeStampMapForSeekingHints: () => Map<number, number>;
|
||||
setTimeStampMapForSeekingHints: (newTimestampMap: Map<number, number>) => void;
|
||||
getTimescale: () => number;
|
||||
setTimescale: (newTimescale: number) => void;
|
||||
addSegment: (seg: Omit<SegmentSection, "index">) => void;
|
||||
addCluster: (cluster: ClusterSection) => void;
|
||||
getFirstCluster: () => ClusterSection | undefined;
|
||||
isInsideSegment: (iterator: BufferIterator) => SegmentSection | null;
|
||||
isInsideCluster: (offset: number) => ClusterSection | null;
|
||||
setAvcProfileForTrackNumber: (trackNumber: number, avcProfile: AvcProfileInfo) => void;
|
||||
getAvcProfileForTrackNumber: (trackNumber: number) => AvcProfileInfo | null;
|
||||
};
|
||||
export type WebmState = ReturnType<typeof webmState>;
|
||||
Generated
Vendored
+130
@@ -0,0 +1,130 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.webmState = void 0;
|
||||
const traversal_1 = require("../../containers/webm/traversal");
|
||||
const lazy_cues_fetch_1 = require("./lazy-cues-fetch");
|
||||
const webmState = ({ controller, logLevel, readerInterface, src, prefetchCache, }) => {
|
||||
const trackEntries = {};
|
||||
const onTrackEntrySegment = (trackEntry) => {
|
||||
var _a;
|
||||
const trackId = (0, traversal_1.getTrackId)(trackEntry);
|
||||
if (!trackId) {
|
||||
throw new Error('Expected track id');
|
||||
}
|
||||
if (trackEntries[trackId]) {
|
||||
return;
|
||||
}
|
||||
const codec = (0, traversal_1.getTrackCodec)(trackEntry);
|
||||
if (!codec) {
|
||||
throw new Error('Expected codec');
|
||||
}
|
||||
const trackTimescale = (0, traversal_1.getTrackTimestampScale)(trackEntry);
|
||||
trackEntries[trackId] = {
|
||||
codec: codec.value,
|
||||
trackTimescale: (_a = trackTimescale === null || trackTimescale === void 0 ? void 0 : trackTimescale.value) !== null && _a !== void 0 ? _a : null,
|
||||
};
|
||||
};
|
||||
let timestampMap = new Map();
|
||||
const getTimestampOffsetForByteOffset = (byteOffset) => {
|
||||
const entries = Array.from(timestampMap.entries());
|
||||
const sortedByByteOffset = entries
|
||||
.sort((a, b) => {
|
||||
return a[0] - b[0];
|
||||
})
|
||||
.reverse();
|
||||
for (const [offset, timestamp] of sortedByByteOffset) {
|
||||
if (offset >= byteOffset) {
|
||||
continue;
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
return timestampMap.get(byteOffset);
|
||||
};
|
||||
const setTimestampOffset = (byteOffset, timestamp) => {
|
||||
timestampMap.set(byteOffset, timestamp);
|
||||
};
|
||||
let timescale = null;
|
||||
const setTimescale = (newTimescale) => {
|
||||
timescale = newTimescale;
|
||||
};
|
||||
const getTimescale = () => {
|
||||
// https://www.matroska.org/technical/notes.html
|
||||
// When using the default value of TimestampScale of “1,000,000”, one Segment Tick represents one millisecond.
|
||||
if (timescale === null) {
|
||||
return 1000000;
|
||||
}
|
||||
return timescale;
|
||||
};
|
||||
const segments = [];
|
||||
const clusters = [];
|
||||
const avcProfilesMap = {};
|
||||
const setAvcProfileForTrackNumber = (trackNumber, avcProfile) => {
|
||||
avcProfilesMap[trackNumber] = avcProfile;
|
||||
};
|
||||
const getAvcProfileForTrackNumber = (trackNumber) => {
|
||||
var _a;
|
||||
return (_a = avcProfilesMap[trackNumber]) !== null && _a !== void 0 ? _a : null;
|
||||
};
|
||||
const cues = (0, lazy_cues_fetch_1.lazyCuesFetch)({
|
||||
controller,
|
||||
logLevel,
|
||||
readerInterface,
|
||||
src,
|
||||
prefetchCache,
|
||||
});
|
||||
const getTimeStampMapForSeekingHints = () => {
|
||||
return timestampMap;
|
||||
};
|
||||
const setTimeStampMapForSeekingHints = (newTimestampMap) => {
|
||||
timestampMap = newTimestampMap;
|
||||
};
|
||||
return {
|
||||
cues,
|
||||
onTrackEntrySegment,
|
||||
getTrackInfoByNumber: (id) => trackEntries[id],
|
||||
setTimestampOffset,
|
||||
getTimestampOffsetForByteOffset,
|
||||
getTimeStampMapForSeekingHints,
|
||||
setTimeStampMapForSeekingHints,
|
||||
getTimescale,
|
||||
setTimescale,
|
||||
addSegment: (seg) => {
|
||||
const segment = {
|
||||
...seg,
|
||||
index: segments.length,
|
||||
};
|
||||
segments.push(segment);
|
||||
},
|
||||
addCluster: (cluster) => {
|
||||
const exists = clusters.some((existingCluster) => existingCluster.start === cluster.start);
|
||||
if (!exists) {
|
||||
clusters.push(cluster);
|
||||
}
|
||||
},
|
||||
getFirstCluster: () => {
|
||||
return clusters.find((cluster) => cluster.segment === 0);
|
||||
},
|
||||
isInsideSegment: (iterator) => {
|
||||
var _a;
|
||||
const offset = iterator.counter.getOffset();
|
||||
const insideClusters = segments.filter((cluster) => {
|
||||
return (offset >= cluster.start && offset <= cluster.start + cluster.size);
|
||||
});
|
||||
if (insideClusters.length > 1) {
|
||||
throw new Error('Expected to only be inside 1 cluster');
|
||||
}
|
||||
return (_a = insideClusters[0]) !== null && _a !== void 0 ? _a : null;
|
||||
},
|
||||
isInsideCluster: (offset) => {
|
||||
for (const cluster of clusters) {
|
||||
if (offset >= cluster.start && offset < cluster.start + cluster.size) {
|
||||
return cluster;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
setAvcProfileForTrackNumber,
|
||||
getAvcProfileForTrackNumber,
|
||||
};
|
||||
};
|
||||
exports.webmState = webmState;
|
||||
skills/remotion-prompt-video/node_modules/@remotion/media-parser/dist/state/may-skip-video-data.d.ts
Generated
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
import type { ParserState } from './parser-state';
|
||||
export declare const missesMatroskaTracks: (state: ParserState) => boolean;
|
||||
export declare const maySkipVideoData: ({ state }: {
|
||||
state: ParserState;
|
||||
}) => boolean;
|
||||
export declare const maySkipOverSamplesInTheMiddle: ({ state, }: {
|
||||
state: ParserState;
|
||||
}) => boolean;
|
||||
Generated
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.maySkipOverSamplesInTheMiddle = exports.maySkipVideoData = exports.missesMatroskaTracks = void 0;
|
||||
const get_ready_tracks_1 = require("../containers/webm/get-ready-tracks");
|
||||
const traversal_1 = require("../containers/webm/traversal");
|
||||
const need_samples_for_fields_1 = require("./need-samples-for-fields");
|
||||
const getHasCallbacks = (state) => {
|
||||
const hasNoTrackHandlers = !state.callbacks.hasAudioTrackHandlers &&
|
||||
!state.callbacks.hasVideoTrackHandlers;
|
||||
if (hasNoTrackHandlers) {
|
||||
return false;
|
||||
}
|
||||
const hasAllTracksAndNoCallbacks = !state.callbacks.tracks.hasAllTracks() ||
|
||||
Object.values(state.callbacks.videoSampleCallbacks).length > 0 ||
|
||||
Object.values(state.callbacks.audioSampleCallbacks).length > 0;
|
||||
return hasAllTracksAndNoCallbacks;
|
||||
};
|
||||
const missesMatroskaTracks = (state) => {
|
||||
const struct = state.structure.getStructureOrNull();
|
||||
if (struct === null) {
|
||||
return false;
|
||||
}
|
||||
if (struct.type !== 'matroska') {
|
||||
return false;
|
||||
}
|
||||
const mainSegment = (0, traversal_1.getMainSegment)(struct.boxes);
|
||||
if (mainSegment === null) {
|
||||
return false;
|
||||
}
|
||||
return ((0, get_ready_tracks_1.getTracksFromMatroska)({
|
||||
structureState: state.structure,
|
||||
webmState: state.webm,
|
||||
}).missingInfo.length > 0);
|
||||
};
|
||||
exports.missesMatroskaTracks = missesMatroskaTracks;
|
||||
const maySkipVideoData = ({ state }) => {
|
||||
const hasCallbacks = getHasCallbacks(state);
|
||||
return (!hasCallbacks &&
|
||||
!(0, need_samples_for_fields_1.needsToIterateOverSamples)({
|
||||
emittedFields: state.emittedFields,
|
||||
fields: state.fields,
|
||||
}) &&
|
||||
!(0, exports.missesMatroskaTracks)(state));
|
||||
};
|
||||
exports.maySkipVideoData = maySkipVideoData;
|
||||
const maySkipOverSamplesInTheMiddle = ({ state, }) => {
|
||||
const hasCallbacks = getHasCallbacks(state);
|
||||
return (!hasCallbacks &&
|
||||
!(0, need_samples_for_fields_1.needsToIterateOverEverySample)({
|
||||
emittedFields: state.emittedFields,
|
||||
fields: state.fields,
|
||||
}));
|
||||
};
|
||||
exports.maySkipOverSamplesInTheMiddle = maySkipOverSamplesInTheMiddle;
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
import type { XingData } from '../containers/mp3/parse-xing';
|
||||
export type Mp3Info = {
|
||||
sampleRate: number;
|
||||
mpegVersion: 1 | 2;
|
||||
layer: number;
|
||||
};
|
||||
export type VariableMp3BitrateInfo = {
|
||||
type: 'variable';
|
||||
xingData: XingData;
|
||||
};
|
||||
export type Mp3BitrateInfo = {
|
||||
type: 'constant';
|
||||
bitrateInKbit: number;
|
||||
} | VariableMp3BitrateInfo;
|
||||
export declare const makeMp3State: () => {
|
||||
getMp3Info: () => Mp3Info | null;
|
||||
setMp3Info: (info: Mp3Info) => void;
|
||||
getMp3BitrateInfo: () => Mp3BitrateInfo | null;
|
||||
setMp3BitrateInfo: (info: Mp3BitrateInfo) => void;
|
||||
audioSamples: {
|
||||
addSample: (audioSampleOffset: import("./audio-sample-map").AudioSampleOffset) => void;
|
||||
getSamples: () => import("./audio-sample-map").AudioSampleOffset[];
|
||||
setFromSeekingHints: (newMap: import("./audio-sample-map").AudioSampleOffset[]) => void;
|
||||
};
|
||||
};
|
||||
export type Mp3State = ReturnType<typeof makeMp3State>;
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeMp3State = void 0;
|
||||
const audio_sample_map_1 = require("./audio-sample-map");
|
||||
const makeMp3State = () => {
|
||||
let mp3Info = null;
|
||||
let bitrateInfo = null;
|
||||
const audioSamples = (0, audio_sample_map_1.audioSampleMapState)();
|
||||
return {
|
||||
getMp3Info: () => mp3Info,
|
||||
setMp3Info: (info) => {
|
||||
mp3Info = info;
|
||||
},
|
||||
getMp3BitrateInfo: () => bitrateInfo,
|
||||
setMp3BitrateInfo: (info) => {
|
||||
bitrateInfo = info;
|
||||
},
|
||||
audioSamples,
|
||||
};
|
||||
};
|
||||
exports.makeMp3State = makeMp3State;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type { AllOptions, Options, ParseMediaFields } from '../fields';
|
||||
export declare const fieldsNeedSamplesMap: Record<keyof Options<ParseMediaFields>, boolean>;
|
||||
export declare const needsToIterateOverSamples: ({ fields, emittedFields, }: {
|
||||
fields: Options<ParseMediaFields>;
|
||||
emittedFields: AllOptions<ParseMediaFields>;
|
||||
}) => boolean;
|
||||
export declare const needsToIterateOverEverySample: ({ fields, emittedFields, }: {
|
||||
fields: Options<ParseMediaFields>;
|
||||
emittedFields: AllOptions<ParseMediaFields>;
|
||||
}) => boolean;
|
||||
Generated
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.needsToIterateOverEverySample = exports.needsToIterateOverSamples = exports.fieldsNeedSamplesMap = void 0;
|
||||
exports.fieldsNeedSamplesMap = {
|
||||
slowDurationInSeconds: true,
|
||||
slowFps: true,
|
||||
slowKeyframes: true,
|
||||
slowNumberOfFrames: true,
|
||||
audioCodec: false,
|
||||
container: false,
|
||||
dimensions: false,
|
||||
durationInSeconds: false,
|
||||
fps: false,
|
||||
internalStats: false,
|
||||
isHdr: false,
|
||||
name: false,
|
||||
rotation: false,
|
||||
size: false,
|
||||
slowStructure: false,
|
||||
tracks: false,
|
||||
unrotatedDimensions: false,
|
||||
videoCodec: false,
|
||||
metadata: false,
|
||||
location: false,
|
||||
mimeType: false,
|
||||
keyframes: false,
|
||||
images: false,
|
||||
numberOfAudioChannels: false,
|
||||
sampleRate: false,
|
||||
slowAudioBitrate: true,
|
||||
slowVideoBitrate: true,
|
||||
m3uStreams: false,
|
||||
};
|
||||
const needsToIterateOverSamples = ({ fields, emittedFields, }) => {
|
||||
const keys = Object.keys(fields !== null && fields !== void 0 ? fields : {});
|
||||
const selectedKeys = keys.filter((k) => fields[k]);
|
||||
return selectedKeys.some((k) => exports.fieldsNeedSamplesMap[k] && !emittedFields[k]);
|
||||
};
|
||||
exports.needsToIterateOverSamples = needsToIterateOverSamples;
|
||||
// For duration, we only need the first and last sample
|
||||
const fieldsNeedEverySampleMap = {
|
||||
...exports.fieldsNeedSamplesMap,
|
||||
slowDurationInSeconds: false,
|
||||
};
|
||||
const needsToIterateOverEverySample = ({ fields, emittedFields, }) => {
|
||||
const keys = Object.keys(fields !== null && fields !== void 0 ? fields : {});
|
||||
const selectedKeys = keys.filter((k) => fields[k]);
|
||||
return selectedKeys.some((k) => fieldsNeedEverySampleMap[k] && !emittedFields[k]);
|
||||
};
|
||||
exports.needsToIterateOverEverySample = needsToIterateOverEverySample;
|
||||
Generated
Vendored
+527
@@ -0,0 +1,527 @@
|
||||
import type { AvcPPs, AvcProfileInfo } from '../containers/avc/parse-avc';
|
||||
import type { SelectM3uAssociatedPlaylistsFn, SelectM3uStreamFn } from '../containers/m3u/select-stream';
|
||||
import type { MediaParserController } from '../controller/media-parser-controller';
|
||||
import type { PrefetchCache } from '../fetch';
|
||||
import type { Options, ParseMediaFields } from '../fields';
|
||||
import { type BufferIterator } from '../iterator/buffer-iterator';
|
||||
import { type MediaParserLogLevel } from '../log';
|
||||
import type { M3uPlaylistContext, OnDiscardedData, ParseMediaCallbacks, ParseMediaMode, ParseMediaSrc } from '../options';
|
||||
import type { MediaParserReaderInterface, Reader } from '../readers/reader';
|
||||
import type { MediaParserOnAudioTrack, MediaParserOnVideoTrack } from '../webcodec-sample-types';
|
||||
export type InternalStats = {
|
||||
skippedBytes: number;
|
||||
finalCursorOffset: number;
|
||||
};
|
||||
export type SpsAndPps = {
|
||||
sps: AvcProfileInfo;
|
||||
pps: AvcPPs;
|
||||
};
|
||||
export declare const makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHandlers, controller, onAudioTrack, onVideoTrack, contentLength, logLevel, mode, src, readerInterface, onDiscardedData, selectM3uStreamFn, selectM3uAssociatedPlaylistsFn, m3uPlaylistContext, contentType, name, callbacks, fieldsInReturnValue, mimeType, initialReaderInstance, makeSamplesStartAtZero, prefetchCache, }: {
|
||||
hasAudioTrackHandlers: boolean;
|
||||
hasVideoTrackHandlers: boolean;
|
||||
controller: MediaParserController;
|
||||
onAudioTrack: MediaParserOnAudioTrack | null;
|
||||
onVideoTrack: MediaParserOnVideoTrack | null;
|
||||
contentLength: number;
|
||||
logLevel: MediaParserLogLevel;
|
||||
mode: ParseMediaMode;
|
||||
src: ParseMediaSrc;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
onDiscardedData: OnDiscardedData | null;
|
||||
selectM3uStreamFn: SelectM3uStreamFn;
|
||||
selectM3uAssociatedPlaylistsFn: SelectM3uAssociatedPlaylistsFn;
|
||||
m3uPlaylistContext: M3uPlaylistContext | null;
|
||||
contentType: string | null;
|
||||
name: string;
|
||||
callbacks: ParseMediaCallbacks;
|
||||
fieldsInReturnValue: Options<ParseMediaFields>;
|
||||
mimeType: string | null;
|
||||
initialReaderInstance: Reader;
|
||||
makeSamplesStartAtZero: boolean;
|
||||
prefetchCache: PrefetchCache;
|
||||
}) => {
|
||||
riff: {
|
||||
getAvcProfile: () => SpsAndPps | null;
|
||||
onProfile: (profile: SpsAndPps) => Promise<void>;
|
||||
registerOnAvcProfileCallback: (callback: (profile: SpsAndPps) => Promise<void>) => void;
|
||||
getNextTrackIndex: () => number;
|
||||
queuedBFrames: {
|
||||
addFrame: ({ frame, maxFramesInBuffer, trackId, timescale, }: {
|
||||
frame: import("./riff/queued-frames").QueuedVideoSample;
|
||||
trackId: number;
|
||||
maxFramesInBuffer: number;
|
||||
timescale: number;
|
||||
}) => void;
|
||||
flush: () => void;
|
||||
getReleasedFrame: () => {
|
||||
sample: import("./riff/queued-frames").QueuedVideoSample;
|
||||
trackId: number;
|
||||
timescale: number;
|
||||
} | null;
|
||||
hasReleasedFrames: () => boolean;
|
||||
clear: () => void;
|
||||
};
|
||||
incrementNextTrackIndex: () => void;
|
||||
lazyIdx1: {
|
||||
triggerLoad: (position: number) => Promise<{
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
}>;
|
||||
getLoadedIdx1: () => Promise<{
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
} | null>;
|
||||
getIfAlreadyLoaded: () => {
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
} | null;
|
||||
setFromSeekingHints: (hints: import("../containers/riff/seeking-hints").RiffSeekingHints) => void;
|
||||
waitForLoaded: () => Promise<{
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
}> | Promise<null>;
|
||||
};
|
||||
sampleCounter: {
|
||||
onAudioSample: (trackId: number, audioSample: import("../webcodec-sample-types").MediaParserAudioSample) => void;
|
||||
onVideoSample: ({ trackId, videoSample, }: {
|
||||
videoSample: import("../webcodec-sample-types").MediaParserVideoSample;
|
||||
trackId: number;
|
||||
}) => void;
|
||||
getSampleCountForTrack: ({ trackId }: {
|
||||
trackId: number;
|
||||
}) => number;
|
||||
setSamplesFromSeek: (samples: Record<number, number>) => void;
|
||||
riffKeys: {
|
||||
addKeyframe: (keyframe: import("./riff/riff-keyframes").RiffKeyframe) => void;
|
||||
getKeyframes: () => import("./riff/riff-keyframes").RiffKeyframe[];
|
||||
setFromSeekingHints: (keyframesFromHints: import("./riff/riff-keyframes").RiffKeyframe[]) => void;
|
||||
};
|
||||
setPocAtKeyframeOffset: ({ keyframeOffset, poc, }: {
|
||||
keyframeOffset: number;
|
||||
poc: number;
|
||||
}) => void;
|
||||
getPocAtKeyframeOffset: ({ keyframeOffset, }: {
|
||||
keyframeOffset: number;
|
||||
}) => number[];
|
||||
getKeyframeAtOffset: (sample: import("./riff/queued-frames").QueuedVideoSample) => number | null;
|
||||
};
|
||||
};
|
||||
transportStream: {
|
||||
nextPesHeaderStore: {
|
||||
setNextPesHeader: (pesHeader: import("../containers/transport-stream/parse-pes").PacketPes) => void;
|
||||
getNextPesHeader: () => import("../containers/transport-stream/parse-pes").PacketPes;
|
||||
};
|
||||
observedPesHeaders: {
|
||||
pesHeaders: import("../containers/transport-stream/parse-pes").PacketPes[];
|
||||
addPesHeader: (pesHeader: import("../containers/transport-stream/parse-pes").PacketPes) => void;
|
||||
markPtsAsKeyframe: (pts: number) => void;
|
||||
getPesKeyframeHeaders: () => import("../containers/transport-stream/parse-pes").PacketPes[];
|
||||
setPesKeyframesFromSeekingHints: (hints: import("../seeking-hints").TransportStreamSeekingHints) => void;
|
||||
};
|
||||
streamBuffers: Map<number, import("../containers/transport-stream/process-stream-buffers").TransportStreamPacketBuffer>;
|
||||
startOffset: {
|
||||
getOffset: (trackId: number) => number;
|
||||
setOffset: ({ newOffset, trackId }: {
|
||||
trackId: number;
|
||||
newOffset: number;
|
||||
}) => void;
|
||||
};
|
||||
resetBeforeSeek: () => void;
|
||||
lastEmittedSample: {
|
||||
setLastEmittedSample: (sample: import("../webcodec-sample-types").MediaParserAudioSample | import("../webcodec-sample-types").MediaParserVideoSample) => void;
|
||||
getLastEmittedSample: () => import("../webcodec-sample-types").MediaParserVideoSample | import("../webcodec-sample-types").MediaParserAudioSample | null;
|
||||
resetLastEmittedSample: () => void;
|
||||
};
|
||||
};
|
||||
webm: {
|
||||
cues: {
|
||||
triggerLoad: (position: number, segmentOffset: number) => Promise<import("../containers/webm/seek/format-cues").MatroskaCue[] | null>;
|
||||
getLoadedCues: () => Promise<{
|
||||
cues: import("../containers/webm/seek/format-cues").MatroskaCue[];
|
||||
segmentOffset: number;
|
||||
} | null>;
|
||||
getIfAlreadyLoaded: () => {
|
||||
cues: import("../containers/webm/seek/format-cues").MatroskaCue[];
|
||||
segmentOffset: number;
|
||||
} | null;
|
||||
setFromSeekingHints: (hints: import("../seeking-hints").WebmSeekingHints) => void;
|
||||
};
|
||||
onTrackEntrySegment: import("../containers/webm/segments").OnTrackEntrySegment;
|
||||
getTrackInfoByNumber: (id: number) => import("../containers/webm/segments/track-entry").TrackInfo;
|
||||
setTimestampOffset: (byteOffset: number, timestamp: number) => void;
|
||||
getTimestampOffsetForByteOffset: (byteOffset: number) => number | undefined;
|
||||
getTimeStampMapForSeekingHints: () => Map<number, number>;
|
||||
setTimeStampMapForSeekingHints: (newTimestampMap: Map<number, number>) => void;
|
||||
getTimescale: () => number;
|
||||
setTimescale: (newTimescale: number) => void;
|
||||
addSegment: (seg: Omit<import("./matroska/webm").SegmentSection, "index">) => void;
|
||||
addCluster: (cluster: import("./matroska/webm").ClusterSection) => void;
|
||||
getFirstCluster: () => import("./matroska/webm").ClusterSection | undefined;
|
||||
isInsideSegment: (iterator: BufferIterator) => import("./matroska/webm").SegmentSection | null;
|
||||
isInsideCluster: (offset: number) => import("./matroska/webm").ClusterSection | null;
|
||||
setAvcProfileForTrackNumber: (trackNumber: number, avcProfile: AvcProfileInfo) => void;
|
||||
getAvcProfileForTrackNumber: (trackNumber: number) => AvcProfileInfo | null;
|
||||
};
|
||||
iso: {
|
||||
flatSamples: {
|
||||
getSamples: (mdatStart: number) => {
|
||||
trackId: number;
|
||||
samplePositions: import("../get-sample-positions").SamplePosition[];
|
||||
}[] | null;
|
||||
setSamples: (mdatStart: number, samples: {
|
||||
trackId: number;
|
||||
samplePositions: import("../get-sample-positions").SamplePosition[];
|
||||
}[]) => void;
|
||||
setCurrentSampleIndex: (mdatStart: number, trackId: number, index: number) => void;
|
||||
getCurrentSampleIndices: (mdatStart: number) => Record<number, number>;
|
||||
updateAfterSeek: (seekedByte: number) => void;
|
||||
};
|
||||
moov: {
|
||||
setMoovBox: (moov: {
|
||||
moovBox: import("../containers/iso-base-media/moov/moov").MoovBox;
|
||||
precomputed: boolean;
|
||||
}) => void;
|
||||
getMoovBoxAndPrecomputed: () => {
|
||||
moovBox: import("../containers/iso-base-media/moov/moov").MoovBox;
|
||||
precomputed: boolean;
|
||||
} | null;
|
||||
};
|
||||
mfra: {
|
||||
triggerLoad: () => Promise<import("../containers/iso-base-media/base-media-box").IsoBaseMediaBox[] | null>;
|
||||
getIfAlreadyLoaded: () => import("../containers/iso-base-media/base-media-box").IsoBaseMediaBox[] | null;
|
||||
setFromSeekingHints: (hints: import("../seeking-hints").IsoBaseMediaSeekingHints) => void;
|
||||
};
|
||||
moof: {
|
||||
getMoofBoxes: () => import("./iso-base-media/precomputed-moof").MoofBox[];
|
||||
setMoofBoxes: (boxes: import("./iso-base-media/precomputed-moof").MoofBox[]) => void;
|
||||
};
|
||||
tfra: {
|
||||
getTfraBoxes: () => import("../containers/iso-base-media/mfra/tfra").TfraBox[];
|
||||
setTfraBoxes: (boxes: import("../containers/iso-base-media/mfra/tfra").TfraBox[]) => void;
|
||||
};
|
||||
movieTimeScale: {
|
||||
getTrackTimescale: () => number | null;
|
||||
setTrackTimescale: (timescale: number) => void;
|
||||
};
|
||||
};
|
||||
mp3: {
|
||||
getMp3Info: () => import("./mp3").Mp3Info | null;
|
||||
setMp3Info: (info: import("./mp3").Mp3Info) => void;
|
||||
getMp3BitrateInfo: () => import("./mp3").Mp3BitrateInfo | null;
|
||||
setMp3BitrateInfo: (info: import("./mp3").Mp3BitrateInfo) => void;
|
||||
audioSamples: {
|
||||
addSample: (audioSampleOffset: import("./audio-sample-map").AudioSampleOffset) => void;
|
||||
getSamples: () => import("./audio-sample-map").AudioSampleOffset[];
|
||||
setFromSeekingHints: (newMap: import("./audio-sample-map").AudioSampleOffset[]) => void;
|
||||
};
|
||||
};
|
||||
aac: {
|
||||
addSample: ({ offset, size }: {
|
||||
offset: number;
|
||||
size: number;
|
||||
}) => {
|
||||
offset: number;
|
||||
index: number;
|
||||
size: number;
|
||||
};
|
||||
getSamples: () => {
|
||||
offset: number;
|
||||
index: number;
|
||||
size: number;
|
||||
}[];
|
||||
audioSamples: {
|
||||
addSample: (audioSampleOffset: import("./audio-sample-map").AudioSampleOffset) => void;
|
||||
getSamples: () => import("./audio-sample-map").AudioSampleOffset[];
|
||||
setFromSeekingHints: (newMap: import("./audio-sample-map").AudioSampleOffset[]) => void;
|
||||
};
|
||||
};
|
||||
flac: {
|
||||
setBlockingBitStrategy: (strategy: number) => void;
|
||||
getBlockingBitStrategy: () => number | undefined;
|
||||
audioSamples: {
|
||||
addSample: (audioSampleOffset: import("./audio-sample-map").AudioSampleOffset) => void;
|
||||
getSamples: () => import("./audio-sample-map").AudioSampleOffset[];
|
||||
setFromSeekingHints: (newMap: import("./audio-sample-map").AudioSampleOffset[]) => void;
|
||||
};
|
||||
};
|
||||
m3u: {
|
||||
setSelectedMainPlaylist: (stream: import("./m3u-state").M3uStreamOrInitialUrl) => void;
|
||||
getSelectedMainPlaylist: () => import("./m3u-state").M3uStreamOrInitialUrl | null;
|
||||
setHasEmittedVideoTrack: (src: string, callback: import("../webcodec-sample-types").MediaParserOnVideoSample | null) => void;
|
||||
hasEmittedVideoTrack: (src: string) => false | import("../webcodec-sample-types").MediaParserOnVideoSample | null;
|
||||
setHasEmittedAudioTrack: (src: string, callback: import("../webcodec-sample-types").MediaParserOnAudioSample | null) => void;
|
||||
hasEmittedAudioTrack: (src: string) => false | import("../webcodec-sample-types").MediaParserOnAudioSample | null;
|
||||
setHasEmittedDoneWithTracks: (src: string) => void;
|
||||
hasEmittedDoneWithTracks: (src: string) => boolean;
|
||||
setReadyToIterateOverM3u: () => void;
|
||||
isReadyToIterateOverM3u: () => boolean;
|
||||
setAllChunksProcessed: (src: string) => void;
|
||||
clearAllChunksProcessed: () => void;
|
||||
getAllChunksProcessedForPlaylist: (src: string) => boolean;
|
||||
getAllChunksProcessedOverall: () => boolean;
|
||||
setHasFinishedManifest: () => void;
|
||||
hasFinishedManifest: () => boolean;
|
||||
setM3uStreamRun: (playlistUrl: string, run: import("./m3u-state").M3uRun | null) => void;
|
||||
setTracksDone: (playlistUrl: string) => boolean;
|
||||
getTrackDone: (playlistUrl: string) => boolean;
|
||||
clearTracksDone: () => void;
|
||||
getM3uStreamRun: (playlistUrl: string) => import("./m3u-state").M3uRun;
|
||||
abortM3UStreamRuns: () => void;
|
||||
setAssociatedPlaylists: (playlists: import("..").M3uAssociatedPlaylist[]) => void;
|
||||
getAssociatedPlaylists: () => import("..").M3uAssociatedPlaylist[] | null;
|
||||
getSelectedPlaylists: () => string[];
|
||||
sampleSorter: {
|
||||
clearSamples: () => void;
|
||||
addToStreamWithTrack: (src: string) => void;
|
||||
addVideoStreamToConsider: (src: string, callback: import("../webcodec-sample-types").MediaParserOnVideoSample) => void;
|
||||
addAudioStreamToConsider: (src: string, callback: import("../webcodec-sample-types").MediaParserOnAudioSample) => void;
|
||||
hasAudioStreamToConsider: (src: string) => boolean;
|
||||
hasVideoStreamToConsider: (src: string) => boolean;
|
||||
addAudioSample: (src: string, sample: import("../webcodec-sample-types").MediaParserAudioSample) => Promise<void>;
|
||||
addVideoSample: (src: string, sample: import("../webcodec-sample-types").MediaParserVideoSample) => Promise<void>;
|
||||
getNextStreamToRun: (streams: string[]) => string;
|
||||
};
|
||||
setMp4HeaderSegment: (playlistUrl: string, structure: import("../parse-result").IsoBaseMediaStructure) => void;
|
||||
getMp4HeaderSegment: (playlistUrl: string) => import("../parse-result").IsoBaseMediaStructure;
|
||||
setSeekToSecondsToProcess: (playlistUrl: string, m3uSeek: {
|
||||
targetTime: number;
|
||||
} | null) => void;
|
||||
getSeekToSecondsToProcess: (playlistUrl: string) => {
|
||||
targetTime: number;
|
||||
} | null;
|
||||
setNextSeekShouldSubtractChunks: (playlistUrl: string, chunks: number) => void;
|
||||
getNextSeekShouldSubtractChunks: (playlistUrl: string) => number;
|
||||
};
|
||||
timings: {
|
||||
timeIterating: number;
|
||||
timeReadingData: number;
|
||||
timeSeeking: number;
|
||||
timeCheckingIfDone: number;
|
||||
timeFreeingData: number;
|
||||
timeInParseLoop: number;
|
||||
};
|
||||
callbacks: {
|
||||
registerVideoSampleCallback: (id: number, callback: import("../webcodec-sample-types").MediaParserOnVideoSample | null) => Promise<void>;
|
||||
onAudioSample: ({ audioSample, trackId, }: {
|
||||
trackId: number;
|
||||
audioSample: import("../webcodec-sample-types").MediaParserAudioSample;
|
||||
}) => Promise<void>;
|
||||
onVideoSample: ({ trackId, videoSample, }: {
|
||||
trackId: number;
|
||||
videoSample: import("../webcodec-sample-types").MediaParserVideoSample;
|
||||
}) => Promise<void>;
|
||||
canSkipTracksState: {
|
||||
doFieldsNeedTracks: () => boolean;
|
||||
canSkipTracks: () => boolean;
|
||||
};
|
||||
registerAudioSampleCallback: (id: number, callback: import("../webcodec-sample-types").MediaParserOnAudioSample | null) => Promise<void>;
|
||||
tracks: {
|
||||
hasAllTracks: () => boolean;
|
||||
getIsDone: () => boolean;
|
||||
setIsDone: (logLevel: MediaParserLogLevel) => void;
|
||||
addTrack: (track: import("..").MediaParserTrack) => void;
|
||||
getTracks: () => import("..").MediaParserTrack[];
|
||||
ensureHasTracksAtEnd: (fields: Options<ParseMediaFields>) => void;
|
||||
};
|
||||
audioSampleCallbacks: Record<number, import("../webcodec-sample-types").MediaParserOnAudioSample>;
|
||||
videoSampleCallbacks: Record<number, import("../webcodec-sample-types").MediaParserOnVideoSample>;
|
||||
hasAudioTrackHandlers: boolean;
|
||||
hasVideoTrackHandlers: boolean;
|
||||
callTracksDoneCallback: () => Promise<void>;
|
||||
};
|
||||
getInternalStats: () => InternalStats;
|
||||
getSkipBytes: () => number;
|
||||
increaseSkippedBytes: (bytes: number) => void;
|
||||
keyframes: {
|
||||
addKeyframe: (keyframe: import("../options").MediaParserKeyframe) => void;
|
||||
getKeyframes: () => import("../options").MediaParserKeyframe[];
|
||||
setFromSeekingHints: (keyframesFromHints: import("../options").MediaParserKeyframe[]) => void;
|
||||
};
|
||||
structure: {
|
||||
getStructureOrNull: () => import("../parse-result").MediaParserStructureUnstable | null;
|
||||
getStructure: () => import("../parse-result").MediaParserStructureUnstable;
|
||||
setStructure: (value: import("../parse-result").MediaParserStructureUnstable) => void;
|
||||
getFlacStructure: () => import("../containers/flac/types").FlacStructure;
|
||||
getIsoStructure: () => import("../parse-result").IsoBaseMediaStructure;
|
||||
getMp3Structure: () => import("../parse-result").Mp3Structure;
|
||||
getM3uStructure: () => import("../containers/m3u/types").M3uStructure;
|
||||
getRiffStructure: () => import("../containers/riff/riff-box").RiffStructure;
|
||||
getTsStructure: () => import("../parse-result").TransportStreamStructure;
|
||||
getWavStructure: () => import("../containers/wav/types").WavStructure;
|
||||
getMatroskaStructure: () => import("../parse-result").MatroskaStructure;
|
||||
};
|
||||
onAudioTrack: MediaParserOnAudioTrack | null;
|
||||
onVideoTrack: MediaParserOnVideoTrack | null;
|
||||
emittedFields: import("../fields").AllOptions<ParseMediaFields>;
|
||||
fields: Partial<import("../fields").AllOptions<ParseMediaFields>>;
|
||||
samplesObserved: {
|
||||
addVideoSample: (videoSample: import("../webcodec-sample-types").MediaParserVideoSample) => void;
|
||||
addAudioSample: (audioSample: import("../webcodec-sample-types").MediaParserAudioSample) => void;
|
||||
getSlowDurationInSeconds: () => number;
|
||||
getFps: () => number;
|
||||
getSlowNumberOfFrames: () => number;
|
||||
getAudioBitrate: () => number | null;
|
||||
getVideoBitrate: () => number | null;
|
||||
getLastSampleObserved: () => boolean;
|
||||
setLastSampleObserved: () => void;
|
||||
getAmountOfSamplesObserved: () => number;
|
||||
};
|
||||
contentLength: number;
|
||||
images: {
|
||||
images: import("./images").MediaParserEmbeddedImage[];
|
||||
addImage: (image: import("./images").MediaParserEmbeddedImage) => void;
|
||||
};
|
||||
mediaSection: {
|
||||
addMediaSection: (section: import("./video-section").MediaSection) => void;
|
||||
getMediaSections: () => import("./video-section").MediaSection[];
|
||||
isCurrentByteInMediaSection: (iterator: BufferIterator) => "no-section-defined" | "in-section" | "outside-section";
|
||||
isByteInMediaSection: ({ position, mediaSections, }: {
|
||||
position: number;
|
||||
mediaSections: import("./video-section").MediaSection[];
|
||||
}) => "no-section-defined" | "in-section" | "outside-section";
|
||||
getCurrentMediaSection: ({ offset, mediaSections, }: {
|
||||
offset: number;
|
||||
mediaSections: import("./video-section").MediaSection[];
|
||||
}) => import("./video-section").MediaSection | null;
|
||||
getMediaSectionAssertOnlyOne: () => import("./video-section").MediaSection;
|
||||
mediaSections: import("./video-section").MediaSection[];
|
||||
};
|
||||
logLevel: "trace" | "verbose" | "info" | "warn" | "error";
|
||||
iterator: {
|
||||
startReadingBits: () => void;
|
||||
stopReadingBits: () => void;
|
||||
skipTo: (offset: number) => void;
|
||||
addData: (newData: Uint8Array) => void;
|
||||
counter: {
|
||||
getOffset: () => number;
|
||||
discardBytes: (bytes: number) => void;
|
||||
increment: (bytes: number) => void;
|
||||
getDiscardedBytes: () => number;
|
||||
setDiscardedOffset: (bytes: number) => void;
|
||||
getDiscardedOffset: () => number;
|
||||
decrement: (bytes: number) => void;
|
||||
};
|
||||
peekB: (length: number) => void;
|
||||
peekD: (length: number) => void;
|
||||
getBits: (bits: number) => number;
|
||||
bytesRemaining: () => number;
|
||||
leb128: () => number;
|
||||
removeBytesRead: (force: boolean, mode: ParseMediaMode) => {
|
||||
bytesRemoved: number;
|
||||
removedData: Uint8Array<ArrayBuffer> | null;
|
||||
};
|
||||
discard: (length: number) => void;
|
||||
getEightByteNumber: (littleEndian?: boolean) => number;
|
||||
getFourByteNumber: () => number;
|
||||
getSlice: (amount: number) => Uint8Array<ArrayBuffer>;
|
||||
getAtom: () => string;
|
||||
detectFileType: () => import("../file-types/detect-file-type").FileType;
|
||||
getPaddedFourByteNumber: () => number;
|
||||
getMatroskaSegmentId: () => string | null;
|
||||
getVint: () => number | null;
|
||||
getUint8: () => number;
|
||||
getEBML: () => number;
|
||||
getInt8: () => number;
|
||||
getUint16: () => number;
|
||||
getUint16Le: () => number;
|
||||
getUint24: () => number;
|
||||
getInt24: () => number;
|
||||
getInt16: () => number;
|
||||
getUint32: () => number;
|
||||
getUint64: (littleEndian?: boolean) => bigint;
|
||||
getInt64: (littleEndian?: boolean) => bigint;
|
||||
getFixedPointUnsigned1616Number: () => number;
|
||||
getFixedPointSigned1616Number: () => number;
|
||||
getFixedPointSigned230Number: () => number;
|
||||
getPascalString: () => number[];
|
||||
getUint(length: number): number;
|
||||
getByteString(length: number, trimTrailingZeroes: boolean): string;
|
||||
planBytes: (size: number) => {
|
||||
discardRest: () => Uint8Array<ArrayBuffer>;
|
||||
};
|
||||
getFloat64: () => number;
|
||||
readUntilNullTerminator: () => string;
|
||||
getFloat32: () => number;
|
||||
getUint32Le: () => number;
|
||||
getInt32Le: () => number;
|
||||
getInt32: () => number;
|
||||
destroy: () => void;
|
||||
startBox: (size: number) => {
|
||||
discardRest: () => void;
|
||||
expectNoMoreBytes: () => void;
|
||||
};
|
||||
readExpGolomb: () => number;
|
||||
startCheckpoint: () => {
|
||||
returnToCheckpoint: () => void;
|
||||
};
|
||||
getFlacCodecNumber: () => number;
|
||||
readUntilLineEnd: () => string | null;
|
||||
getSyncSafeInt32: () => number;
|
||||
replaceData: (newData: Uint8Array, seekTo: number) => void;
|
||||
};
|
||||
controller: MediaParserController;
|
||||
mode: ParseMediaMode;
|
||||
src: ParseMediaSrc;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
discardReadBytes: (force: boolean) => Promise<void>;
|
||||
selectM3uStreamFn: SelectM3uStreamFn;
|
||||
selectM3uAssociatedPlaylistsFn: SelectM3uAssociatedPlaylistsFn;
|
||||
m3uPlaylistContext: M3uPlaylistContext | null;
|
||||
contentType: string | null;
|
||||
name: string;
|
||||
returnValue: {
|
||||
dimensions: import("..").MediaParserDimensions | null;
|
||||
durationInSeconds: number | null;
|
||||
slowDurationInSeconds: number;
|
||||
slowNumberOfFrames: number;
|
||||
slowFps: number;
|
||||
slowStructure: import("../parse-result").MediaParserStructureUnstable;
|
||||
fps: number | null;
|
||||
videoCodec: import("..").MediaParserVideoCodec | null;
|
||||
audioCodec: import("..").MediaParserAudioCodec | null;
|
||||
tracks: import("..").MediaParserTrack[];
|
||||
rotation: number | null;
|
||||
unrotatedDimensions: import("..").MediaParserDimensions | null;
|
||||
internalStats: InternalStats;
|
||||
size: number | null;
|
||||
name: string;
|
||||
container: import("../options").MediaParserContainer;
|
||||
isHdr: boolean;
|
||||
metadata: import("..").MediaParserMetadataEntry[];
|
||||
location: import("..").MediaParserLocation | null;
|
||||
mimeType: string | null;
|
||||
keyframes: import("../options").MediaParserKeyframe[] | null;
|
||||
slowKeyframes: import("../options").MediaParserKeyframe[];
|
||||
images: import("./images").MediaParserEmbeddedImage[];
|
||||
sampleRate: number | null;
|
||||
numberOfAudioChannels: number | null;
|
||||
slowVideoBitrate: number | null;
|
||||
slowAudioBitrate: number | null;
|
||||
m3uStreams: import("..").M3uStream[] | null;
|
||||
};
|
||||
callbackFunctions: Partial<import("../options").ParseMediaCallbacksMandatory>;
|
||||
fieldsInReturnValue: Partial<import("../fields").AllOptions<ParseMediaFields>>;
|
||||
mimeType: string | null;
|
||||
errored: Error | null;
|
||||
currentReader: {
|
||||
getCurrent: () => Reader;
|
||||
setCurrent: (newReader: Reader) => void;
|
||||
};
|
||||
seekInfiniteLoop: {
|
||||
registerSeek: (byte: number) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
makeSamplesStartAtZero: boolean;
|
||||
prefetchCache: PrefetchCache;
|
||||
avc: {
|
||||
getPrevPicOrderCntLsb(): number;
|
||||
getPrevPicOrderCntMsb(): number;
|
||||
setPrevPicOrderCntLsb(value: number): void;
|
||||
setPrevPicOrderCntMsb(value: number): void;
|
||||
setSps(value: import("../containers/avc/parse-avc").SpsInfo): void;
|
||||
getSps(): import("../containers/avc/parse-avc").SpsInfo | null;
|
||||
getMaxFramesInBuffer(): number | null;
|
||||
clear(): void;
|
||||
};
|
||||
};
|
||||
export type ParserState = ReturnType<typeof makeParserState>;
|
||||
Generated
Vendored
+148
@@ -0,0 +1,148 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeParserState = void 0;
|
||||
const get_fields_from_callbacks_1 = require("../get-fields-from-callbacks");
|
||||
const buffer_iterator_1 = require("../iterator/buffer-iterator");
|
||||
const log_1 = require("../log");
|
||||
const aac_state_1 = require("./aac-state");
|
||||
const avc_state_1 = require("./avc/avc-state");
|
||||
const current_reader_1 = require("./current-reader");
|
||||
const emitted_fields_1 = require("./emitted-fields");
|
||||
const flac_state_1 = require("./flac-state");
|
||||
const images_1 = require("./images");
|
||||
const iso_state_1 = require("./iso-base-media/iso-state");
|
||||
const keyframes_1 = require("./keyframes");
|
||||
const m3u_state_1 = require("./m3u-state");
|
||||
const webm_1 = require("./matroska/webm");
|
||||
const mp3_1 = require("./mp3");
|
||||
const riff_1 = require("./riff");
|
||||
const sample_callbacks_1 = require("./sample-callbacks");
|
||||
const slow_duration_fps_1 = require("./samples-observed/slow-duration-fps");
|
||||
const seek_infinite_loop_1 = require("./seek-infinite-loop");
|
||||
const structure_1 = require("./structure");
|
||||
const timings_1 = require("./timings");
|
||||
const transport_stream_1 = require("./transport-stream/transport-stream");
|
||||
const video_section_1 = require("./video-section");
|
||||
const makeParserState = ({ hasAudioTrackHandlers, hasVideoTrackHandlers, controller, onAudioTrack, onVideoTrack, contentLength, logLevel, mode, src, readerInterface, onDiscardedData, selectM3uStreamFn, selectM3uAssociatedPlaylistsFn, m3uPlaylistContext, contentType, name, callbacks, fieldsInReturnValue, mimeType, initialReaderInstance, makeSamplesStartAtZero, prefetchCache, }) => {
|
||||
let skippedBytes = 0;
|
||||
const returnValue = {};
|
||||
const iterator = (0, buffer_iterator_1.getArrayBufferIterator)({
|
||||
initialData: new Uint8Array([]),
|
||||
maxBytes: contentLength,
|
||||
logLevel,
|
||||
});
|
||||
const increaseSkippedBytes = (bytes) => {
|
||||
skippedBytes += bytes;
|
||||
};
|
||||
const structure = (0, structure_1.structureState)();
|
||||
const keyframes = (0, keyframes_1.keyframesState)();
|
||||
const emittedFields = (0, emitted_fields_1.emittedState)();
|
||||
const samplesObserved = (0, slow_duration_fps_1.samplesObservedState)();
|
||||
const mp3 = (0, mp3_1.makeMp3State)();
|
||||
const images = (0, images_1.imagesState)();
|
||||
const timings = (0, timings_1.timingsState)();
|
||||
const seekInfiniteLoop = (0, seek_infinite_loop_1.seekInfiniteLoopDetectionState)();
|
||||
const currentReaderState = (0, current_reader_1.currentReader)(initialReaderInstance);
|
||||
const avc = (0, avc_state_1.avcState)();
|
||||
const errored = null;
|
||||
const discardReadBytes = async (force) => {
|
||||
const { bytesRemoved, removedData } = iterator.removeBytesRead(force, mode);
|
||||
if (bytesRemoved) {
|
||||
log_1.Log.verbose(logLevel, `Freed ${bytesRemoved} bytes`);
|
||||
}
|
||||
if (removedData && onDiscardedData) {
|
||||
await onDiscardedData(removedData);
|
||||
}
|
||||
};
|
||||
const fields = (0, get_fields_from_callbacks_1.getFieldsFromCallback)({
|
||||
fields: fieldsInReturnValue,
|
||||
callbacks,
|
||||
});
|
||||
const mediaSection = (0, video_section_1.mediaSectionState)();
|
||||
return {
|
||||
riff: (0, riff_1.riffSpecificState)({
|
||||
controller,
|
||||
logLevel,
|
||||
readerInterface,
|
||||
src,
|
||||
prefetchCache,
|
||||
contentLength,
|
||||
}),
|
||||
transportStream: (0, transport_stream_1.transportStreamState)(),
|
||||
webm: (0, webm_1.webmState)({
|
||||
controller,
|
||||
logLevel,
|
||||
readerInterface,
|
||||
src,
|
||||
prefetchCache,
|
||||
}),
|
||||
iso: (0, iso_state_1.isoBaseMediaState)({
|
||||
contentLength,
|
||||
controller,
|
||||
readerInterface,
|
||||
src,
|
||||
logLevel,
|
||||
prefetchCache,
|
||||
}),
|
||||
mp3,
|
||||
aac: (0, aac_state_1.aacState)(),
|
||||
flac: (0, flac_state_1.flacState)(),
|
||||
m3u: (0, m3u_state_1.m3uState)(logLevel),
|
||||
timings,
|
||||
callbacks: (0, sample_callbacks_1.callbacksState)({
|
||||
controller,
|
||||
hasAudioTrackHandlers,
|
||||
hasVideoTrackHandlers,
|
||||
fields,
|
||||
keyframes,
|
||||
emittedFields,
|
||||
samplesObserved,
|
||||
structure,
|
||||
src,
|
||||
seekSignal: controller._internals.seekSignal,
|
||||
logLevel,
|
||||
}),
|
||||
getInternalStats: () => {
|
||||
var _a;
|
||||
return ({
|
||||
skippedBytes,
|
||||
finalCursorOffset: (_a = iterator.counter.getOffset()) !== null && _a !== void 0 ? _a : 0,
|
||||
});
|
||||
},
|
||||
getSkipBytes: () => skippedBytes,
|
||||
increaseSkippedBytes,
|
||||
keyframes,
|
||||
structure,
|
||||
onAudioTrack,
|
||||
onVideoTrack,
|
||||
emittedFields,
|
||||
fields,
|
||||
samplesObserved,
|
||||
contentLength,
|
||||
images,
|
||||
mediaSection,
|
||||
logLevel,
|
||||
iterator,
|
||||
controller,
|
||||
mode,
|
||||
src,
|
||||
readerInterface,
|
||||
discardReadBytes,
|
||||
selectM3uStreamFn,
|
||||
selectM3uAssociatedPlaylistsFn,
|
||||
m3uPlaylistContext,
|
||||
contentType,
|
||||
name,
|
||||
returnValue,
|
||||
callbackFunctions: callbacks,
|
||||
fieldsInReturnValue,
|
||||
mimeType,
|
||||
errored: errored,
|
||||
currentReader: currentReaderState,
|
||||
seekInfiniteLoop,
|
||||
makeSamplesStartAtZero,
|
||||
prefetchCache,
|
||||
avc,
|
||||
};
|
||||
};
|
||||
exports.makeParserState = makeParserState;
|
||||
Generated
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
import type { MediaParserController } from '../controller/media-parser-controller';
|
||||
import type { PrefetchCache } from '../fetch';
|
||||
import type { MediaParserLogLevel } from '../log';
|
||||
import type { ParseMediaSrc } from '../options';
|
||||
import type { MediaParserReaderInterface } from '../readers/reader';
|
||||
import type { SpsAndPps } from './parser-state';
|
||||
type AvcProfileInfoCallback = (profile: SpsAndPps) => Promise<void>;
|
||||
export declare const riffSpecificState: ({ controller, logLevel, readerInterface, src, prefetchCache, contentLength, }: {
|
||||
controller: MediaParserController;
|
||||
logLevel: MediaParserLogLevel;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
src: ParseMediaSrc;
|
||||
prefetchCache: PrefetchCache;
|
||||
contentLength: number;
|
||||
}) => {
|
||||
getAvcProfile: () => SpsAndPps | null;
|
||||
onProfile: (profile: SpsAndPps) => Promise<void>;
|
||||
registerOnAvcProfileCallback: (callback: AvcProfileInfoCallback) => void;
|
||||
getNextTrackIndex: () => number;
|
||||
queuedBFrames: {
|
||||
addFrame: ({ frame, maxFramesInBuffer, trackId, timescale, }: {
|
||||
frame: import("./riff/queued-frames").QueuedVideoSample;
|
||||
trackId: number;
|
||||
maxFramesInBuffer: number;
|
||||
timescale: number;
|
||||
}) => void;
|
||||
flush: () => void;
|
||||
getReleasedFrame: () => {
|
||||
sample: import("./riff/queued-frames").QueuedVideoSample;
|
||||
trackId: number;
|
||||
timescale: number;
|
||||
} | null;
|
||||
hasReleasedFrames: () => boolean;
|
||||
clear: () => void;
|
||||
};
|
||||
incrementNextTrackIndex: () => void;
|
||||
lazyIdx1: {
|
||||
triggerLoad: (position: number) => Promise<{
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
}>;
|
||||
getLoadedIdx1: () => Promise<{
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
} | null>;
|
||||
getIfAlreadyLoaded: () => {
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
} | null;
|
||||
setFromSeekingHints: (hints: import("../containers/riff/seeking-hints").RiffSeekingHints) => void;
|
||||
waitForLoaded: () => Promise<{
|
||||
entries: import("../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
}> | Promise<null>;
|
||||
};
|
||||
sampleCounter: {
|
||||
onAudioSample: (trackId: number, audioSample: import("..").MediaParserAudioSample) => void;
|
||||
onVideoSample: ({ trackId, videoSample, }: {
|
||||
videoSample: import("..").MediaParserVideoSample;
|
||||
trackId: number;
|
||||
}) => void;
|
||||
getSampleCountForTrack: ({ trackId }: {
|
||||
trackId: number;
|
||||
}) => number;
|
||||
setSamplesFromSeek: (samples: Record<number, number>) => void;
|
||||
riffKeys: {
|
||||
addKeyframe: (keyframe: import("./riff/riff-keyframes").RiffKeyframe) => void;
|
||||
getKeyframes: () => import("./riff/riff-keyframes").RiffKeyframe[];
|
||||
setFromSeekingHints: (keyframesFromHints: import("./riff/riff-keyframes").RiffKeyframe[]) => void;
|
||||
};
|
||||
setPocAtKeyframeOffset: ({ keyframeOffset, poc, }: {
|
||||
keyframeOffset: number;
|
||||
poc: number;
|
||||
}) => void;
|
||||
getPocAtKeyframeOffset: ({ keyframeOffset, }: {
|
||||
keyframeOffset: number;
|
||||
}) => number[];
|
||||
getKeyframeAtOffset: (sample: import("./riff/queued-frames").QueuedVideoSample) => number | null;
|
||||
};
|
||||
};
|
||||
export type RiffState = ReturnType<typeof riffSpecificState>;
|
||||
export {};
|
||||
Generated
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.riffSpecificState = void 0;
|
||||
const lazy_idx1_fetch_1 = require("./riff/lazy-idx1-fetch");
|
||||
const queued_frames_1 = require("./riff/queued-frames");
|
||||
const sample_counter_1 = require("./riff/sample-counter");
|
||||
const riffSpecificState = ({ controller, logLevel, readerInterface, src, prefetchCache, contentLength, }) => {
|
||||
let avcProfile = null;
|
||||
let nextTrackIndex = 0;
|
||||
const profileCallbacks = [];
|
||||
const registerOnAvcProfileCallback = (callback) => {
|
||||
profileCallbacks.push(callback);
|
||||
};
|
||||
const onProfile = async (profile) => {
|
||||
avcProfile = profile;
|
||||
for (const callback of profileCallbacks) {
|
||||
await callback(profile);
|
||||
}
|
||||
profileCallbacks.length = 0;
|
||||
};
|
||||
const lazyIdx1 = (0, lazy_idx1_fetch_1.lazyIdx1Fetch)({
|
||||
controller,
|
||||
logLevel,
|
||||
readerInterface,
|
||||
src,
|
||||
prefetchCache,
|
||||
contentLength,
|
||||
});
|
||||
const sampleCounter = (0, sample_counter_1.riffSampleCounter)();
|
||||
const queuedBFrames = (0, queued_frames_1.queuedBFramesState)();
|
||||
return {
|
||||
getAvcProfile: () => {
|
||||
return avcProfile;
|
||||
},
|
||||
onProfile,
|
||||
registerOnAvcProfileCallback,
|
||||
getNextTrackIndex: () => {
|
||||
return nextTrackIndex;
|
||||
},
|
||||
queuedBFrames,
|
||||
incrementNextTrackIndex: () => {
|
||||
nextTrackIndex++;
|
||||
},
|
||||
lazyIdx1,
|
||||
sampleCounter,
|
||||
};
|
||||
};
|
||||
exports.riffSpecificState = riffSpecificState;
|
||||
Generated
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
import type { RiffSeekingHints } from '../../containers/riff/seeking-hints';
|
||||
import type { MediaParserController } from '../../controller/media-parser-controller';
|
||||
import type { PrefetchCache } from '../../fetch';
|
||||
import type { MediaParserLogLevel } from '../../log';
|
||||
import type { ParseMediaSrc } from '../../options';
|
||||
import type { MediaParserReaderInterface } from '../../readers/reader';
|
||||
export declare const lazyIdx1Fetch: ({ controller, logLevel, readerInterface, src, prefetchCache, contentLength, }: {
|
||||
controller: MediaParserController;
|
||||
logLevel: MediaParserLogLevel;
|
||||
readerInterface: MediaParserReaderInterface;
|
||||
src: ParseMediaSrc;
|
||||
prefetchCache: PrefetchCache;
|
||||
contentLength: number;
|
||||
}) => {
|
||||
triggerLoad: (position: number) => Promise<{
|
||||
entries: import("../../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
}>;
|
||||
getLoadedIdx1: () => Promise<{
|
||||
entries: import("../../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
} | null>;
|
||||
getIfAlreadyLoaded: () => {
|
||||
entries: import("../../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
} | null;
|
||||
setFromSeekingHints: (hints: RiffSeekingHints) => void;
|
||||
waitForLoaded: () => Promise<{
|
||||
entries: import("../../containers/riff/riff-box").Idx1Entry[];
|
||||
videoTrackIndex: number | null;
|
||||
}> | Promise<null>;
|
||||
};
|
||||
export type LazyIdx1Fetch = ReturnType<typeof lazyIdx1Fetch>;
|
||||
Generated
Vendored
+65
@@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.lazyIdx1Fetch = void 0;
|
||||
const fetch_idx1_1 = require("../../containers/riff/seek/fetch-idx1");
|
||||
const lazyIdx1Fetch = ({ controller, logLevel, readerInterface, src, prefetchCache, contentLength, }) => {
|
||||
let prom = null;
|
||||
let result = null;
|
||||
const triggerLoad = (position) => {
|
||||
if (result) {
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
if (prom) {
|
||||
return prom;
|
||||
}
|
||||
prom = (0, fetch_idx1_1.fetchIdx1)({
|
||||
controller,
|
||||
logLevel,
|
||||
position,
|
||||
readerInterface,
|
||||
src,
|
||||
prefetchCache,
|
||||
contentLength,
|
||||
}).then((entries) => {
|
||||
prom = null;
|
||||
result = entries;
|
||||
return entries;
|
||||
});
|
||||
return prom;
|
||||
};
|
||||
const getLoadedIdx1 = async () => {
|
||||
if (!prom) {
|
||||
return null;
|
||||
}
|
||||
const entries = await prom;
|
||||
return entries;
|
||||
};
|
||||
const getIfAlreadyLoaded = () => {
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const setFromSeekingHints = (hints) => {
|
||||
if (hints.idx1Entries) {
|
||||
result = hints.idx1Entries;
|
||||
}
|
||||
};
|
||||
const waitForLoaded = () => {
|
||||
if (result) {
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
if (prom) {
|
||||
return prom;
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
};
|
||||
return {
|
||||
triggerLoad,
|
||||
getLoadedIdx1,
|
||||
getIfAlreadyLoaded,
|
||||
setFromSeekingHints,
|
||||
waitForLoaded,
|
||||
};
|
||||
};
|
||||
exports.lazyIdx1Fetch = lazyIdx1Fetch;
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
import type { MediaParserVideoSample } from '../../webcodec-sample-types';
|
||||
export type QueuedVideoSample = Omit<MediaParserVideoSample, 'decodingTimestamp' | 'timestamp'>;
|
||||
type QueueItem = {
|
||||
sample: QueuedVideoSample;
|
||||
trackId: number;
|
||||
timescale: number;
|
||||
};
|
||||
export declare const queuedBFramesState: () => {
|
||||
addFrame: ({ frame, maxFramesInBuffer, trackId, timescale, }: {
|
||||
frame: QueuedVideoSample;
|
||||
trackId: number;
|
||||
maxFramesInBuffer: number;
|
||||
timescale: number;
|
||||
}) => void;
|
||||
flush: () => void;
|
||||
getReleasedFrame: () => QueueItem | null;
|
||||
hasReleasedFrames: () => boolean;
|
||||
clear: () => void;
|
||||
};
|
||||
export {};
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.queuedBFramesState = void 0;
|
||||
const queuedBFramesState = () => {
|
||||
const queuedFrames = [];
|
||||
const releasedFrames = [];
|
||||
const flush = () => {
|
||||
releasedFrames.push(...queuedFrames);
|
||||
queuedFrames.length = 0;
|
||||
};
|
||||
return {
|
||||
addFrame: ({ frame, maxFramesInBuffer, trackId, timescale, }) => {
|
||||
if (frame.type === 'key') {
|
||||
flush();
|
||||
releasedFrames.push({ sample: frame, trackId, timescale });
|
||||
return;
|
||||
}
|
||||
queuedFrames.push({ sample: frame, trackId, timescale });
|
||||
if (queuedFrames.length > maxFramesInBuffer) {
|
||||
releasedFrames.push(queuedFrames.shift());
|
||||
}
|
||||
},
|
||||
flush,
|
||||
getReleasedFrame: () => {
|
||||
if (releasedFrames.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return releasedFrames.shift();
|
||||
},
|
||||
hasReleasedFrames: () => {
|
||||
return releasedFrames.length > 0;
|
||||
},
|
||||
clear: () => {
|
||||
releasedFrames.length = 0;
|
||||
queuedFrames.length = 0;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.queuedBFramesState = queuedBFramesState;
|
||||
skills/remotion-prompt-video/node_modules/@remotion/media-parser/dist/state/riff/riff-keyframes.d.ts
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type { MediaParserKeyframe } from '../../options';
|
||||
export type RiffKeyframe = MediaParserKeyframe & {
|
||||
sampleCounts: Record<number, number>;
|
||||
};
|
||||
export declare const riffKeyframesState: () => {
|
||||
addKeyframe: (keyframe: RiffKeyframe) => void;
|
||||
getKeyframes: () => RiffKeyframe[];
|
||||
setFromSeekingHints: (keyframesFromHints: RiffKeyframe[]) => void;
|
||||
};
|
||||
export type RiffKeyframesState = ReturnType<typeof riffKeyframesState>;
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.riffKeyframesState = void 0;
|
||||
const riffKeyframesState = () => {
|
||||
const keyframes = [];
|
||||
const addKeyframe = (keyframe) => {
|
||||
if (keyframes.find((k) => k.positionInBytes === keyframe.positionInBytes)) {
|
||||
return;
|
||||
}
|
||||
keyframes.push(keyframe);
|
||||
keyframes.sort((a, b) => a.positionInBytes - b.positionInBytes);
|
||||
};
|
||||
const getKeyframes = () => {
|
||||
return keyframes;
|
||||
};
|
||||
const setFromSeekingHints = (keyframesFromHints) => {
|
||||
for (const keyframe of keyframesFromHints) {
|
||||
addKeyframe(keyframe);
|
||||
}
|
||||
};
|
||||
return {
|
||||
addKeyframe,
|
||||
getKeyframes,
|
||||
setFromSeekingHints,
|
||||
};
|
||||
};
|
||||
exports.riffKeyframesState = riffKeyframesState;
|
||||
skills/remotion-prompt-video/node_modules/@remotion/media-parser/dist/state/riff/sample-counter.d.ts
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
import type { MediaParserAudioSample, MediaParserVideoSample } from '../../webcodec-sample-types';
|
||||
import type { QueuedVideoSample } from './queued-frames';
|
||||
export declare const riffSampleCounter: () => {
|
||||
onAudioSample: (trackId: number, audioSample: MediaParserAudioSample) => void;
|
||||
onVideoSample: ({ trackId, videoSample, }: {
|
||||
videoSample: MediaParserVideoSample;
|
||||
trackId: number;
|
||||
}) => void;
|
||||
getSampleCountForTrack: ({ trackId }: {
|
||||
trackId: number;
|
||||
}) => number;
|
||||
setSamplesFromSeek: (samples: Record<number, number>) => void;
|
||||
riffKeys: {
|
||||
addKeyframe: (keyframe: import("./riff-keyframes").RiffKeyframe) => void;
|
||||
getKeyframes: () => import("./riff-keyframes").RiffKeyframe[];
|
||||
setFromSeekingHints: (keyframesFromHints: import("./riff-keyframes").RiffKeyframe[]) => void;
|
||||
};
|
||||
setPocAtKeyframeOffset: ({ keyframeOffset, poc, }: {
|
||||
keyframeOffset: number;
|
||||
poc: number;
|
||||
}) => void;
|
||||
getPocAtKeyframeOffset: ({ keyframeOffset, }: {
|
||||
keyframeOffset: number;
|
||||
}) => number[];
|
||||
getKeyframeAtOffset: (sample: QueuedVideoSample) => number | null;
|
||||
};
|
||||
Generated
Vendored
+80
@@ -0,0 +1,80 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.riffSampleCounter = void 0;
|
||||
const webcodecs_timescale_1 = require("../../webcodecs-timescale");
|
||||
const riff_keyframes_1 = require("./riff-keyframes");
|
||||
const riffSampleCounter = () => {
|
||||
const samplesForTrack = {};
|
||||
// keyframe offset -> poc[]
|
||||
const pocsAtKeyframeOffset = {};
|
||||
const riffKeys = (0, riff_keyframes_1.riffKeyframesState)();
|
||||
const onAudioSample = (trackId, audioSample) => {
|
||||
if (typeof samplesForTrack[trackId] === 'undefined') {
|
||||
samplesForTrack[trackId] = 0;
|
||||
}
|
||||
if (audioSample.data.length > 0) {
|
||||
samplesForTrack[trackId]++;
|
||||
}
|
||||
samplesForTrack[trackId]++;
|
||||
};
|
||||
const onVideoSample = ({ trackId, videoSample, }) => {
|
||||
if (typeof samplesForTrack[trackId] === 'undefined') {
|
||||
samplesForTrack[trackId] = 0;
|
||||
}
|
||||
if (videoSample.type === 'key') {
|
||||
riffKeys.addKeyframe({
|
||||
trackId,
|
||||
decodingTimeInSeconds: videoSample.decodingTimestamp / webcodecs_timescale_1.WEBCODECS_TIMESCALE,
|
||||
positionInBytes: videoSample.offset,
|
||||
presentationTimeInSeconds: videoSample.timestamp / webcodecs_timescale_1.WEBCODECS_TIMESCALE,
|
||||
sizeInBytes: videoSample.data.length,
|
||||
sampleCounts: { ...samplesForTrack },
|
||||
});
|
||||
}
|
||||
if (videoSample.data.length > 0) {
|
||||
samplesForTrack[trackId]++;
|
||||
}
|
||||
};
|
||||
const getSampleCountForTrack = ({ trackId }) => {
|
||||
var _a;
|
||||
return (_a = samplesForTrack[trackId]) !== null && _a !== void 0 ? _a : 0;
|
||||
};
|
||||
const setSamplesFromSeek = (samples) => {
|
||||
for (const trackId in samples) {
|
||||
samplesForTrack[trackId] = samples[trackId];
|
||||
}
|
||||
};
|
||||
const setPocAtKeyframeOffset = ({ keyframeOffset, poc, }) => {
|
||||
if (typeof pocsAtKeyframeOffset[keyframeOffset] === 'undefined') {
|
||||
pocsAtKeyframeOffset[keyframeOffset] = [];
|
||||
}
|
||||
if (pocsAtKeyframeOffset[keyframeOffset].includes(poc)) {
|
||||
return;
|
||||
}
|
||||
pocsAtKeyframeOffset[keyframeOffset].push(poc);
|
||||
pocsAtKeyframeOffset[keyframeOffset].sort((a, b) => a - b);
|
||||
};
|
||||
const getPocAtKeyframeOffset = ({ keyframeOffset, }) => {
|
||||
return pocsAtKeyframeOffset[keyframeOffset];
|
||||
};
|
||||
const getKeyframeAtOffset = (sample) => {
|
||||
var _a, _b;
|
||||
if (sample.type === 'key') {
|
||||
return sample.offset;
|
||||
}
|
||||
return ((_b = (_a = riffKeys
|
||||
.getKeyframes()
|
||||
.findLast((k) => k.positionInBytes <= sample.offset)) === null || _a === void 0 ? void 0 : _a.positionInBytes) !== null && _b !== void 0 ? _b : null);
|
||||
};
|
||||
return {
|
||||
onAudioSample,
|
||||
onVideoSample,
|
||||
getSampleCountForTrack,
|
||||
setSamplesFromSeek,
|
||||
riffKeys,
|
||||
setPocAtKeyframeOffset,
|
||||
getPocAtKeyframeOffset,
|
||||
getKeyframeAtOffset,
|
||||
};
|
||||
};
|
||||
exports.riffSampleCounter = riffSampleCounter;
|
||||
Generated
Vendored
+51
@@ -0,0 +1,51 @@
|
||||
import type { MediaParserController } from '../controller/media-parser-controller';
|
||||
import type { SeekSignal } from '../controller/seek-signal';
|
||||
import type { AllOptions, Options, ParseMediaFields } from '../fields';
|
||||
import type { MediaParserLogLevel } from '../log';
|
||||
import type { ParseMediaSrc } from '../options';
|
||||
import type { MediaParserAudioSample, MediaParserOnAudioSample, MediaParserOnVideoSample, MediaParserVideoSample } from '../webcodec-sample-types';
|
||||
import { type KeyframesState } from './keyframes';
|
||||
import type { SamplesObservedState } from './samples-observed/slow-duration-fps';
|
||||
import type { StructureState } from './structure';
|
||||
export declare const callbacksState: ({ controller, hasAudioTrackHandlers, hasVideoTrackHandlers, fields, keyframes, emittedFields, samplesObserved, structure, src, seekSignal, logLevel, }: {
|
||||
controller: MediaParserController;
|
||||
hasAudioTrackHandlers: boolean;
|
||||
hasVideoTrackHandlers: boolean;
|
||||
fields: Options<ParseMediaFields>;
|
||||
keyframes: KeyframesState;
|
||||
emittedFields: AllOptions<ParseMediaFields>;
|
||||
samplesObserved: SamplesObservedState;
|
||||
structure: StructureState;
|
||||
src: ParseMediaSrc;
|
||||
seekSignal: SeekSignal;
|
||||
logLevel: MediaParserLogLevel;
|
||||
}) => {
|
||||
registerVideoSampleCallback: (id: number, callback: MediaParserOnVideoSample | null) => Promise<void>;
|
||||
onAudioSample: ({ audioSample, trackId, }: {
|
||||
trackId: number;
|
||||
audioSample: MediaParserAudioSample;
|
||||
}) => Promise<void>;
|
||||
onVideoSample: ({ trackId, videoSample, }: {
|
||||
trackId: number;
|
||||
videoSample: MediaParserVideoSample;
|
||||
}) => Promise<void>;
|
||||
canSkipTracksState: {
|
||||
doFieldsNeedTracks: () => boolean;
|
||||
canSkipTracks: () => boolean;
|
||||
};
|
||||
registerAudioSampleCallback: (id: number, callback: MediaParserOnAudioSample | null) => Promise<void>;
|
||||
tracks: {
|
||||
hasAllTracks: () => boolean;
|
||||
getIsDone: () => boolean;
|
||||
setIsDone: (logLevel: MediaParserLogLevel) => void;
|
||||
addTrack: (track: import("..").MediaParserTrack) => void;
|
||||
getTracks: () => import("..").MediaParserTrack[];
|
||||
ensureHasTracksAtEnd: (fields: Options<ParseMediaFields>) => void;
|
||||
};
|
||||
audioSampleCallbacks: Record<number, MediaParserOnAudioSample>;
|
||||
videoSampleCallbacks: Record<number, MediaParserOnVideoSample>;
|
||||
hasAudioTrackHandlers: boolean;
|
||||
hasVideoTrackHandlers: boolean;
|
||||
callTracksDoneCallback: () => Promise<void>;
|
||||
};
|
||||
export type CallbacksState = ReturnType<typeof callbacksState>;
|
||||
Generated
Vendored
+116
@@ -0,0 +1,116 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.callbacksState = void 0;
|
||||
const log_1 = require("../log");
|
||||
const webcodecs_timescale_1 = require("../webcodecs-timescale");
|
||||
const can_skip_tracks_1 = require("./can-skip-tracks");
|
||||
const has_tracks_section_1 = require("./has-tracks-section");
|
||||
const need_samples_for_fields_1 = require("./need-samples-for-fields");
|
||||
const callbacksState = ({ controller, hasAudioTrackHandlers, hasVideoTrackHandlers, fields, keyframes, emittedFields, samplesObserved, structure, src, seekSignal, logLevel, }) => {
|
||||
const videoSampleCallbacks = {};
|
||||
const audioSampleCallbacks = {};
|
||||
const onTrackDoneCallback = {};
|
||||
const queuedAudioSamples = {};
|
||||
const queuedVideoSamples = {};
|
||||
const canSkipTracksState = (0, can_skip_tracks_1.makeCanSkipTracksState)({
|
||||
hasAudioTrackHandlers,
|
||||
fields,
|
||||
hasVideoTrackHandlers,
|
||||
structure,
|
||||
});
|
||||
const tracksState = (0, has_tracks_section_1.makeTracksSectionState)(canSkipTracksState, src);
|
||||
return {
|
||||
registerVideoSampleCallback: async (id, callback) => {
|
||||
var _a;
|
||||
if (callback === null) {
|
||||
delete videoSampleCallbacks[id];
|
||||
return;
|
||||
}
|
||||
videoSampleCallbacks[id] = callback;
|
||||
for (const queued of (_a = queuedVideoSamples[id]) !== null && _a !== void 0 ? _a : []) {
|
||||
await callback(queued);
|
||||
}
|
||||
queuedVideoSamples[id] = [];
|
||||
},
|
||||
onAudioSample: async ({ audioSample, trackId, }) => {
|
||||
if (controller._internals.signal.aborted) {
|
||||
throw new Error('Aborted');
|
||||
}
|
||||
const callback = audioSampleCallbacks[trackId];
|
||||
if (audioSample.data.length > 0) {
|
||||
// If we emit samples with data length 0, Chrome will fail
|
||||
if (callback) {
|
||||
if (seekSignal.getSeek() !== null) {
|
||||
log_1.Log.trace(logLevel, 'Not emitting sample because seek is processing');
|
||||
}
|
||||
else {
|
||||
const trackDoneCallback = await callback(audioSample);
|
||||
onTrackDoneCallback[trackId] = trackDoneCallback !== null && trackDoneCallback !== void 0 ? trackDoneCallback : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((0, need_samples_for_fields_1.needsToIterateOverSamples)({ emittedFields, fields })) {
|
||||
samplesObserved.addAudioSample(audioSample);
|
||||
}
|
||||
},
|
||||
onVideoSample: async ({ trackId, videoSample, }) => {
|
||||
if (controller._internals.signal.aborted) {
|
||||
throw new Error('Aborted');
|
||||
}
|
||||
if (videoSample.data.length > 0) {
|
||||
const callback = videoSampleCallbacks[trackId];
|
||||
// If we emit samples with data 0, Chrome will fail
|
||||
if (callback) {
|
||||
if (seekSignal.getSeek() !== null) {
|
||||
log_1.Log.trace(logLevel, 'Not emitting sample because seek is processing');
|
||||
}
|
||||
else {
|
||||
const trackDoneCallback = await callback(videoSample);
|
||||
onTrackDoneCallback[trackId] = trackDoneCallback !== null && trackDoneCallback !== void 0 ? trackDoneCallback : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (videoSample.type === 'key') {
|
||||
keyframes.addKeyframe({
|
||||
trackId,
|
||||
decodingTimeInSeconds: videoSample.decodingTimestamp / webcodecs_timescale_1.WEBCODECS_TIMESCALE,
|
||||
positionInBytes: videoSample.offset,
|
||||
presentationTimeInSeconds: videoSample.timestamp / webcodecs_timescale_1.WEBCODECS_TIMESCALE,
|
||||
sizeInBytes: videoSample.data.length,
|
||||
});
|
||||
}
|
||||
if ((0, need_samples_for_fields_1.needsToIterateOverSamples)({
|
||||
fields,
|
||||
emittedFields,
|
||||
})) {
|
||||
samplesObserved.addVideoSample(videoSample);
|
||||
}
|
||||
},
|
||||
canSkipTracksState,
|
||||
registerAudioSampleCallback: async (id, callback) => {
|
||||
var _a;
|
||||
if (callback === null) {
|
||||
delete audioSampleCallbacks[id];
|
||||
return;
|
||||
}
|
||||
audioSampleCallbacks[id] = callback;
|
||||
for (const queued of (_a = queuedAudioSamples[id]) !== null && _a !== void 0 ? _a : []) {
|
||||
await callback(queued);
|
||||
}
|
||||
queuedAudioSamples[id] = [];
|
||||
},
|
||||
tracks: tracksState,
|
||||
audioSampleCallbacks,
|
||||
videoSampleCallbacks,
|
||||
hasAudioTrackHandlers,
|
||||
hasVideoTrackHandlers,
|
||||
callTracksDoneCallback: async () => {
|
||||
for (const callback of Object.values(onTrackDoneCallback)) {
|
||||
if (callback) {
|
||||
await callback();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.callbacksState = callbacksState;
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
import type { MediaParserAudioSample, MediaParserVideoSample } from '../../webcodec-sample-types';
|
||||
export declare const samplesObservedState: () => {
|
||||
addVideoSample: (videoSample: MediaParserVideoSample) => void;
|
||||
addAudioSample: (audioSample: MediaParserAudioSample) => void;
|
||||
getSlowDurationInSeconds: () => number;
|
||||
getFps: () => number;
|
||||
getSlowNumberOfFrames: () => number;
|
||||
getAudioBitrate: () => number | null;
|
||||
getVideoBitrate: () => number | null;
|
||||
getLastSampleObserved: () => boolean;
|
||||
setLastSampleObserved: () => void;
|
||||
getAmountOfSamplesObserved: () => number;
|
||||
};
|
||||
export type SamplesObservedState = ReturnType<typeof samplesObservedState>;
|
||||
Generated
Vendored
+96
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.samplesObservedState = void 0;
|
||||
const webcodecs_timescale_1 = require("../../webcodecs-timescale");
|
||||
const samplesObservedState = () => {
|
||||
let smallestVideoSample;
|
||||
let largestVideoSample;
|
||||
let smallestAudioSample;
|
||||
let largestAudioSample;
|
||||
let lastSampleObserved = false;
|
||||
const videoSamples = new Map();
|
||||
const audioSamples = new Map();
|
||||
const getSlowVideoDurationInSeconds = () => {
|
||||
return (largestVideoSample !== null && largestVideoSample !== void 0 ? largestVideoSample : 0) - (smallestVideoSample !== null && smallestVideoSample !== void 0 ? smallestVideoSample : 0);
|
||||
};
|
||||
const getSlowAudioDurationInSeconds = () => {
|
||||
return (largestAudioSample !== null && largestAudioSample !== void 0 ? largestAudioSample : 0) - (smallestAudioSample !== null && smallestAudioSample !== void 0 ? smallestAudioSample : 0);
|
||||
};
|
||||
const getSlowDurationInSeconds = () => {
|
||||
const smallestSample = Math.min(smallestAudioSample !== null && smallestAudioSample !== void 0 ? smallestAudioSample : Infinity, smallestVideoSample !== null && smallestVideoSample !== void 0 ? smallestVideoSample : Infinity);
|
||||
const largestSample = Math.max(largestAudioSample !== null && largestAudioSample !== void 0 ? largestAudioSample : 0, largestVideoSample !== null && largestVideoSample !== void 0 ? largestVideoSample : 0);
|
||||
if (smallestSample === Infinity || largestSample === Infinity) {
|
||||
return 0;
|
||||
}
|
||||
return largestSample - smallestSample;
|
||||
};
|
||||
const addVideoSample = (videoSample) => {
|
||||
var _a;
|
||||
videoSamples.set(videoSample.timestamp, videoSample.data.byteLength);
|
||||
const presentationTimeInSeconds = videoSample.timestamp / webcodecs_timescale_1.WEBCODECS_TIMESCALE;
|
||||
const duration = ((_a = videoSample.duration) !== null && _a !== void 0 ? _a : 0) / webcodecs_timescale_1.WEBCODECS_TIMESCALE;
|
||||
if (largestVideoSample === undefined ||
|
||||
presentationTimeInSeconds > largestVideoSample) {
|
||||
largestVideoSample = presentationTimeInSeconds + duration;
|
||||
}
|
||||
if (smallestVideoSample === undefined ||
|
||||
presentationTimeInSeconds < smallestVideoSample) {
|
||||
smallestVideoSample = presentationTimeInSeconds;
|
||||
}
|
||||
};
|
||||
const addAudioSample = (audioSample) => {
|
||||
var _a;
|
||||
audioSamples.set(audioSample.timestamp, audioSample.data.byteLength);
|
||||
const presentationTimeInSeconds = audioSample.timestamp / webcodecs_timescale_1.WEBCODECS_TIMESCALE;
|
||||
const duration = ((_a = audioSample.duration) !== null && _a !== void 0 ? _a : 0) / webcodecs_timescale_1.WEBCODECS_TIMESCALE;
|
||||
if (largestAudioSample === undefined ||
|
||||
presentationTimeInSeconds > largestAudioSample) {
|
||||
largestAudioSample = presentationTimeInSeconds + duration;
|
||||
}
|
||||
if (smallestAudioSample === undefined ||
|
||||
presentationTimeInSeconds < smallestAudioSample) {
|
||||
smallestAudioSample = presentationTimeInSeconds;
|
||||
}
|
||||
};
|
||||
const getFps = () => {
|
||||
const videoDuration = (largestVideoSample !== null && largestVideoSample !== void 0 ? largestVideoSample : 0) - (smallestVideoSample !== null && smallestVideoSample !== void 0 ? smallestVideoSample : 0);
|
||||
if (videoDuration === 0) {
|
||||
return 0;
|
||||
}
|
||||
return (videoSamples.size - 1) / videoDuration;
|
||||
};
|
||||
const getSlowNumberOfFrames = () => videoSamples.size;
|
||||
const getAudioBitrate = () => {
|
||||
const audioDuration = getSlowAudioDurationInSeconds();
|
||||
if (audioDuration === 0 || audioSamples.size === 0) {
|
||||
return null;
|
||||
}
|
||||
const audioSizesInBytes = Array.from(audioSamples.values()).reduce((acc, size) => acc + size, 0);
|
||||
return (audioSizesInBytes * 8) / audioDuration;
|
||||
};
|
||||
const getVideoBitrate = () => {
|
||||
const videoDuration = getSlowVideoDurationInSeconds();
|
||||
if (videoDuration === 0 || videoSamples.size === 0) {
|
||||
return null;
|
||||
}
|
||||
const videoSizesInBytes = Array.from(videoSamples.values()).reduce((acc, size) => acc + size, 0);
|
||||
return (videoSizesInBytes * 8) / videoDuration;
|
||||
};
|
||||
const getLastSampleObserved = () => lastSampleObserved;
|
||||
const setLastSampleObserved = () => {
|
||||
lastSampleObserved = true;
|
||||
};
|
||||
return {
|
||||
addVideoSample,
|
||||
addAudioSample,
|
||||
getSlowDurationInSeconds,
|
||||
getFps,
|
||||
getSlowNumberOfFrames,
|
||||
getAudioBitrate,
|
||||
getVideoBitrate,
|
||||
getLastSampleObserved,
|
||||
setLastSampleObserved,
|
||||
getAmountOfSamplesObserved: () => videoSamples.size + audioSamples.size,
|
||||
};
|
||||
};
|
||||
exports.samplesObservedState = samplesObservedState;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
export declare const seekInfiniteLoopDetectionState: () => {
|
||||
registerSeek: (byte: number) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
export type SeekInfiniteLoop = ReturnType<typeof seekInfiniteLoopDetectionState>;
|
||||
Generated
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.seekInfiniteLoopDetectionState = void 0;
|
||||
const seekInfiniteLoopDetectionState = () => {
|
||||
let lastSeek = null;
|
||||
let firstSeekTime = null;
|
||||
return {
|
||||
registerSeek: (byte) => {
|
||||
const now = Date.now();
|
||||
if (!lastSeek || lastSeek.byte !== byte) {
|
||||
lastSeek = { byte, numberOfTimes: 1 };
|
||||
firstSeekTime = now;
|
||||
return;
|
||||
}
|
||||
lastSeek.numberOfTimes++;
|
||||
if (lastSeek.numberOfTimes >= 10 &&
|
||||
firstSeekTime &&
|
||||
now - firstSeekTime <= 2000) {
|
||||
throw new Error(`Seeking infinite loop detected: Seeked to byte 0x${byte.toString(16)} ${lastSeek.numberOfTimes} times in a row in the last 2 seconds. Check your usage of .seek().`);
|
||||
}
|
||||
if (now - firstSeekTime > 2000) {
|
||||
lastSeek = { byte, numberOfTimes: 1 };
|
||||
firstSeekTime = now;
|
||||
}
|
||||
},
|
||||
reset: () => {
|
||||
lastSeek = null;
|
||||
firstSeekTime = null;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.seekInfiniteLoopDetectionState = seekInfiniteLoopDetectionState;
|
||||
Generated
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
import type { MediaParserStructureUnstable } from '../parse-result';
|
||||
export declare const structureState: () => {
|
||||
getStructureOrNull: () => MediaParserStructureUnstable | null;
|
||||
getStructure: () => MediaParserStructureUnstable;
|
||||
setStructure: (value: MediaParserStructureUnstable) => void;
|
||||
getFlacStructure: () => import("../containers/flac/types").FlacStructure;
|
||||
getIsoStructure: () => import("../parse-result").IsoBaseMediaStructure;
|
||||
getMp3Structure: () => import("../parse-result").Mp3Structure;
|
||||
getM3uStructure: () => import("../containers/m3u/types").M3uStructure;
|
||||
getRiffStructure: () => import("../containers/riff/riff-box").RiffStructure;
|
||||
getTsStructure: () => import("../parse-result").TransportStreamStructure;
|
||||
getWavStructure: () => import("../containers/wav/types").WavStructure;
|
||||
getMatroskaStructure: () => import("../parse-result").MatroskaStructure;
|
||||
};
|
||||
export type StructureState = ReturnType<typeof structureState>;
|
||||
Generated
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.structureState = void 0;
|
||||
const structureState = () => {
|
||||
let structure = null;
|
||||
const getStructure = () => {
|
||||
if (structure === null) {
|
||||
throw new Error('Expected structure');
|
||||
}
|
||||
return structure;
|
||||
};
|
||||
return {
|
||||
getStructureOrNull: () => {
|
||||
return structure;
|
||||
},
|
||||
getStructure,
|
||||
setStructure: (value) => {
|
||||
structure = value;
|
||||
},
|
||||
getFlacStructure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'flac') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
getIsoStructure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'iso-base-media') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
getMp3Structure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'mp3') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
getM3uStructure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'm3u') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
getRiffStructure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'riff') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
getTsStructure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'transport-stream') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
getWavStructure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'wav') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
getMatroskaStructure: () => {
|
||||
const struc = getStructure();
|
||||
if (struc.type !== 'matroska') {
|
||||
throw new Error('Invalid structure type');
|
||||
}
|
||||
return struc;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.structureState = structureState;
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
export declare const timingsState: () => {
|
||||
timeIterating: number;
|
||||
timeReadingData: number;
|
||||
timeSeeking: number;
|
||||
timeCheckingIfDone: number;
|
||||
timeFreeingData: number;
|
||||
timeInParseLoop: number;
|
||||
};
|
||||
export type TimingsState = ReturnType<typeof timingsState>;
|
||||
Generated
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.timingsState = void 0;
|
||||
const timingsState = () => {
|
||||
return {
|
||||
timeIterating: 0,
|
||||
timeReadingData: 0,
|
||||
timeSeeking: 0,
|
||||
timeCheckingIfDone: 0,
|
||||
timeFreeingData: 0,
|
||||
timeInParseLoop: 0,
|
||||
};
|
||||
};
|
||||
exports.timingsState = timingsState;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import type { MediaParserAudioSample, MediaParserVideoSample } from '../../webcodec-sample-types';
|
||||
export declare const lastEmittedSampleState: () => {
|
||||
setLastEmittedSample: (sample: MediaParserAudioSample | MediaParserVideoSample) => void;
|
||||
getLastEmittedSample: () => MediaParserVideoSample | MediaParserAudioSample | null;
|
||||
resetLastEmittedSample: () => void;
|
||||
};
|
||||
Generated
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.lastEmittedSampleState = void 0;
|
||||
const lastEmittedSampleState = () => {
|
||||
let lastEmittedSample = null;
|
||||
return {
|
||||
setLastEmittedSample: (sample) => {
|
||||
lastEmittedSample = sample;
|
||||
},
|
||||
getLastEmittedSample: () => lastEmittedSample,
|
||||
resetLastEmittedSample: () => {
|
||||
lastEmittedSample = null;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.lastEmittedSampleState = lastEmittedSampleState;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import type { PacketPes } from '../../containers/transport-stream/parse-pes';
|
||||
export declare const makeNextPesHeaderStore: () => {
|
||||
setNextPesHeader: (pesHeader: PacketPes) => void;
|
||||
getNextPesHeader: () => PacketPes;
|
||||
};
|
||||
export type NextPesHeaderStore = ReturnType<typeof makeNextPesHeaderStore>;
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeNextPesHeaderStore = void 0;
|
||||
const makeNextPesHeaderStore = () => {
|
||||
let nextPesHeader = null;
|
||||
return {
|
||||
setNextPesHeader: (pesHeader) => {
|
||||
nextPesHeader = pesHeader;
|
||||
},
|
||||
getNextPesHeader: () => {
|
||||
if (!nextPesHeader) {
|
||||
throw new Error('No next PES header found');
|
||||
}
|
||||
return nextPesHeader;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.makeNextPesHeaderStore = makeNextPesHeaderStore;
|
||||
Generated
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
import type { PacketPes } from '../../containers/transport-stream/parse-pes';
|
||||
import type { TransportStreamSeekingHints } from '../../seeking-hints';
|
||||
export declare const makeObservedPesHeader: () => {
|
||||
pesHeaders: PacketPes[];
|
||||
addPesHeader: (pesHeader: PacketPes) => void;
|
||||
markPtsAsKeyframe: (pts: number) => void;
|
||||
getPesKeyframeHeaders: () => PacketPes[];
|
||||
setPesKeyframesFromSeekingHints: (hints: TransportStreamSeekingHints) => void;
|
||||
};
|
||||
export type ObservedPesHeaderState = ReturnType<typeof makeObservedPesHeader>;
|
||||
export declare const getLastKeyFrameBeforeTimeInSeconds: ({ observedPesHeaders, timeInSeconds, ptsStartOffset, }: {
|
||||
observedPesHeaders: ObservedPesHeaderState["pesHeaders"];
|
||||
timeInSeconds: number;
|
||||
ptsStartOffset: number;
|
||||
}) => PacketPes | undefined;
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getLastKeyFrameBeforeTimeInSeconds = exports.makeObservedPesHeader = void 0;
|
||||
const handle_avc_packet_1 = require("../../containers/transport-stream/handle-avc-packet");
|
||||
const makeObservedPesHeader = () => {
|
||||
const pesHeaders = [];
|
||||
const confirmedAsKeyframe = [];
|
||||
const addPesHeader = (pesHeader) => {
|
||||
if (pesHeaders.find((p) => p.offset === pesHeader.offset)) {
|
||||
return;
|
||||
}
|
||||
pesHeaders.push(pesHeader);
|
||||
};
|
||||
const markPtsAsKeyframe = (pts) => {
|
||||
confirmedAsKeyframe.push(pts);
|
||||
};
|
||||
const getPesKeyframeHeaders = () => {
|
||||
return pesHeaders.filter((p) => confirmedAsKeyframe.includes(p.pts));
|
||||
};
|
||||
const setPesKeyframesFromSeekingHints = (hints) => {
|
||||
for (const pesHeader of hints.observedPesHeaders) {
|
||||
addPesHeader(pesHeader);
|
||||
markPtsAsKeyframe(pesHeader.pts);
|
||||
}
|
||||
};
|
||||
const state = {
|
||||
pesHeaders,
|
||||
addPesHeader,
|
||||
markPtsAsKeyframe,
|
||||
getPesKeyframeHeaders,
|
||||
setPesKeyframesFromSeekingHints,
|
||||
};
|
||||
return state;
|
||||
};
|
||||
exports.makeObservedPesHeader = makeObservedPesHeader;
|
||||
const getLastKeyFrameBeforeTimeInSeconds = ({ observedPesHeaders, timeInSeconds, ptsStartOffset, }) => {
|
||||
return observedPesHeaders.findLast((k) => (k.pts - ptsStartOffset) / handle_avc_packet_1.MPEG_TIMESCALE <= timeInSeconds);
|
||||
};
|
||||
exports.getLastKeyFrameBeforeTimeInSeconds = getLastKeyFrameBeforeTimeInSeconds;
|
||||
Generated
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
export declare const ptsStartOffsetStore: () => {
|
||||
getOffset: (trackId: number) => number;
|
||||
setOffset: ({ newOffset, trackId }: {
|
||||
trackId: number;
|
||||
newOffset: number;
|
||||
}) => void;
|
||||
};
|
||||
export type PtsStartOffsetState = ReturnType<typeof ptsStartOffsetStore>;
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ptsStartOffsetStore = void 0;
|
||||
const ptsStartOffsetStore = () => {
|
||||
const offsets = {};
|
||||
return {
|
||||
getOffset: (trackId) => offsets[trackId] || 0,
|
||||
setOffset: ({ newOffset, trackId }) => {
|
||||
offsets[trackId] = newOffset;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.ptsStartOffsetStore = ptsStartOffsetStore;
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
import type { TransportStreamPacketBuffer } from '../../containers/transport-stream/process-stream-buffers';
|
||||
export declare const transportStreamState: () => {
|
||||
nextPesHeaderStore: {
|
||||
setNextPesHeader: (pesHeader: import("../../containers/transport-stream/parse-pes").PacketPes) => void;
|
||||
getNextPesHeader: () => import("../../containers/transport-stream/parse-pes").PacketPes;
|
||||
};
|
||||
observedPesHeaders: {
|
||||
pesHeaders: import("../../containers/transport-stream/parse-pes").PacketPes[];
|
||||
addPesHeader: (pesHeader: import("../../containers/transport-stream/parse-pes").PacketPes) => void;
|
||||
markPtsAsKeyframe: (pts: number) => void;
|
||||
getPesKeyframeHeaders: () => import("../../containers/transport-stream/parse-pes").PacketPes[];
|
||||
setPesKeyframesFromSeekingHints: (hints: import("../../seeking-hints").TransportStreamSeekingHints) => void;
|
||||
};
|
||||
streamBuffers: Map<number, TransportStreamPacketBuffer>;
|
||||
startOffset: {
|
||||
getOffset: (trackId: number) => number;
|
||||
setOffset: ({ newOffset, trackId }: {
|
||||
trackId: number;
|
||||
newOffset: number;
|
||||
}) => void;
|
||||
};
|
||||
resetBeforeSeek: () => void;
|
||||
lastEmittedSample: {
|
||||
setLastEmittedSample: (sample: import("../..").MediaParserAudioSample | import("../..").MediaParserVideoSample) => void;
|
||||
getLastEmittedSample: () => import("../..").MediaParserVideoSample | import("../..").MediaParserAudioSample | null;
|
||||
resetLastEmittedSample: () => void;
|
||||
};
|
||||
};
|
||||
export type TransportStreamState = ReturnType<typeof transportStreamState>;
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transportStreamState = void 0;
|
||||
const last_emitted_sample_1 = require("./last-emitted-sample");
|
||||
const next_pes_header_store_1 = require("./next-pes-header-store");
|
||||
const observed_pes_header_1 = require("./observed-pes-header");
|
||||
const pts_start_offset_1 = require("./pts-start-offset");
|
||||
const transportStreamState = () => {
|
||||
const streamBuffers = new Map();
|
||||
const startOffset = (0, pts_start_offset_1.ptsStartOffsetStore)();
|
||||
const lastEmittedSample = (0, last_emitted_sample_1.lastEmittedSampleState)();
|
||||
const state = {
|
||||
nextPesHeaderStore: (0, next_pes_header_store_1.makeNextPesHeaderStore)(),
|
||||
observedPesHeaders: (0, observed_pes_header_1.makeObservedPesHeader)(),
|
||||
streamBuffers,
|
||||
startOffset,
|
||||
resetBeforeSeek: () => {
|
||||
state.streamBuffers.clear();
|
||||
state.nextPesHeaderStore = (0, next_pes_header_store_1.makeNextPesHeaderStore)();
|
||||
// start offset is useful, we can keep it
|
||||
},
|
||||
lastEmittedSample,
|
||||
};
|
||||
return state;
|
||||
};
|
||||
exports.transportStreamState = transportStreamState;
|
||||
Generated
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Keeps track of in which section of the file the video is playing
|
||||
* Usually this section is in a different format and it is the only section
|
||||
* that can be read partially
|
||||
*/
|
||||
import type { BufferIterator } from '../iterator/buffer-iterator';
|
||||
export type MediaSection = {
|
||||
start: number;
|
||||
size: number;
|
||||
};
|
||||
export declare const isByteInMediaSection: ({ position, mediaSections, }: {
|
||||
position: number;
|
||||
mediaSections: MediaSection[];
|
||||
}) => "no-section-defined" | "in-section" | "outside-section";
|
||||
export declare const getCurrentMediaSection: ({ offset, mediaSections, }: {
|
||||
offset: number;
|
||||
mediaSections: MediaSection[];
|
||||
}) => MediaSection | null;
|
||||
export declare const mediaSectionState: () => {
|
||||
addMediaSection: (section: MediaSection) => void;
|
||||
getMediaSections: () => MediaSection[];
|
||||
isCurrentByteInMediaSection: (iterator: BufferIterator) => "no-section-defined" | "in-section" | "outside-section";
|
||||
isByteInMediaSection: ({ position, mediaSections, }: {
|
||||
position: number;
|
||||
mediaSections: MediaSection[];
|
||||
}) => "no-section-defined" | "in-section" | "outside-section";
|
||||
getCurrentMediaSection: ({ offset, mediaSections, }: {
|
||||
offset: number;
|
||||
mediaSections: MediaSection[];
|
||||
}) => MediaSection | null;
|
||||
getMediaSectionAssertOnlyOne: () => MediaSection;
|
||||
mediaSections: MediaSection[];
|
||||
};
|
||||
export type MediaSectionState = ReturnType<typeof mediaSectionState>;
|
||||
Generated
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Keeps track of in which section of the file the video is playing
|
||||
* Usually this section is in a different format and it is the only section
|
||||
* that can be read partially
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.mediaSectionState = exports.getCurrentMediaSection = exports.isByteInMediaSection = void 0;
|
||||
const isByteInMediaSection = ({ position, mediaSections, }) => {
|
||||
if (mediaSections.length === 0) {
|
||||
return 'no-section-defined';
|
||||
}
|
||||
for (const section of mediaSections) {
|
||||
if (position >= section.start && position < section.start + section.size) {
|
||||
return 'in-section';
|
||||
}
|
||||
}
|
||||
return 'outside-section';
|
||||
};
|
||||
exports.isByteInMediaSection = isByteInMediaSection;
|
||||
const getCurrentMediaSection = ({ offset, mediaSections, }) => {
|
||||
for (const section of mediaSections) {
|
||||
if (offset >= section.start && offset < section.start + section.size) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
exports.getCurrentMediaSection = getCurrentMediaSection;
|
||||
const mediaSectionState = () => {
|
||||
const mediaSections = [];
|
||||
const addMediaSection = (section) => {
|
||||
// Check if section overlaps with any existing sections
|
||||
const overlaps = mediaSections.some((existingSection) => section.start < existingSection.start + existingSection.size &&
|
||||
section.start + section.size > existingSection.start);
|
||||
if (overlaps) {
|
||||
return;
|
||||
}
|
||||
// Remove any existing sections that are encompassed by the new section
|
||||
// Needed by Matroska because we need to define a 1 byte media section
|
||||
// when seeking into a Cluster we have not seen yet
|
||||
for (let i = mediaSections.length - 1; i >= 0; i--) {
|
||||
const existingSection = mediaSections[i];
|
||||
if (section.start <= existingSection.start &&
|
||||
section.start + section.size >=
|
||||
existingSection.start + existingSection.size) {
|
||||
mediaSections.splice(i, 1);
|
||||
}
|
||||
}
|
||||
mediaSections.push(section);
|
||||
};
|
||||
const getMediaSections = () => {
|
||||
return mediaSections;
|
||||
};
|
||||
const isCurrentByteInMediaSection = (iterator) => {
|
||||
const offset = iterator.counter.getOffset();
|
||||
return (0, exports.isByteInMediaSection)({
|
||||
position: offset,
|
||||
mediaSections,
|
||||
});
|
||||
};
|
||||
const getMediaSectionAssertOnlyOne = () => {
|
||||
if (mediaSections.length !== 1) {
|
||||
throw new Error('Expected only one video section');
|
||||
}
|
||||
return mediaSections[0];
|
||||
};
|
||||
return {
|
||||
addMediaSection,
|
||||
getMediaSections,
|
||||
isCurrentByteInMediaSection,
|
||||
isByteInMediaSection: exports.isByteInMediaSection,
|
||||
getCurrentMediaSection: exports.getCurrentMediaSection,
|
||||
getMediaSectionAssertOnlyOne,
|
||||
mediaSections,
|
||||
};
|
||||
};
|
||||
exports.mediaSectionState = mediaSectionState;
|
||||
Reference in New Issue
Block a user