import { SerialRunner, Task } from "../../../core/tasks/task.js"; import { createMachineActor } from "../../../core/actors/create-machine-actor.js"; import { appendSegment } from "../../../media/dom/mse/append-segment.js"; import { flushBuffer } from "../../../media/dom/mse/buffer-flusher.js"; import { SEGMENT_TIME_EPSILON } from "../../../media/types/index.js"; //#region src/playback/actors/dom/source-buffer.ts function snapshotBuffered(buffered) { const ranges = []; for (let i = 0; i < buffered.length; i++) ranges.push({ start: buffered.start(i), end: buffered.end(i) }); return ranges; } function appendInitTask(message, { getContext, sourceBuffer }) { return new Task(async (taskSignal) => { const ctx = getContext(); if (taskSignal.aborted) return ctx; await appendSegment(sourceBuffer, message.data); return { ...ctx, initTrackId: message.meta.trackId, initTrackLanguage: message.meta.language }; }); } function appendSegmentTask(message, { getContext, sourceBuffer, setContext }) { return new Task(async (taskSignal) => { const ctx = getContext(); if (taskSignal.aborted) return ctx; const { meta } = message; const filtered = ctx.segments.filter((s) => Math.abs(s.startTime - meta.startTime) >= SEGMENT_TIME_EPSILON); if (!(message.data instanceof ArrayBuffer)) setContext({ ...ctx, segments: [...filtered, { id: meta.id, startTime: meta.startTime, duration: meta.duration, trackId: meta.trackId, ...meta.trackBandwidth !== void 0 && { trackBandwidth: meta.trackBandwidth }, partial: true }], bufferedRanges: ctx.bufferedRanges }); if (meta.timestampOffset != null && sourceBuffer.timestampOffset !== meta.timestampOffset) sourceBuffer.timestampOffset = meta.timestampOffset; await appendSegment(sourceBuffer, message.data, taskSignal); return { ...ctx, segments: [...filtered, { id: meta.id, startTime: meta.startTime, duration: meta.duration, trackId: meta.trackId, ...meta.trackBandwidth !== void 0 && { trackBandwidth: meta.trackBandwidth } }], bufferedRanges: snapshotBuffered(sourceBuffer.buffered) }; }); } function removeTask(message, { getContext, sourceBuffer }) { return new Task(async (taskSignal) => { const ctx = getContext(); if (taskSignal.aborted) return ctx; await flushBuffer(sourceBuffer, message.start, message.end); const bufferedRanges = snapshotBuffered(sourceBuffer.buffered); const filtered = ctx.segments.filter((s) => { const midpoint = s.startTime + s.duration / 2; return bufferedRanges.some((r) => midpoint >= r.start && midpoint < r.end); }); return { ...ctx, segments: filtered, bufferedRanges }; }); } const messageTaskFactories = { "append-init": appendInitTask, "append-segment": appendSegmentTask, remove: removeTask }; function messageToTask(message, options) { const factory = messageTaskFactories[message.type]; return factory(message, options); } function createSourceBufferActor(sourceBuffer, initialContext) { const handleError = (e) => { if (!(e instanceof Error && e.name === "AbortError")) console.error("SourceBuffer operation failed:", e); }; const onMessage = (msg, { transition, setContext, getContext, runner }) => { transition("updating"); const task = messageToTask(msg, { getContext, sourceBuffer, setContext }); runner.schedule(task).then(setContext, handleError); }; return createMachineActor({ runner: () => new SerialRunner(), initial: "idle", context: { segments: [], bufferedRanges: [], initTrackId: void 0, ...initialContext }, states: { idle: { on: { "append-init": onMessage, "append-segment": onMessage, remove: onMessage, batch: (msg, { transition, setContext, getContext, runner }) => { const { messages } = msg; if (messages.length === 0) return; transition("updating"); messages.forEach((msg) => { const task = messageToTask(msg, { getContext, sourceBuffer, setContext }); runner.schedule(task).then(setContext, handleError); }); } } }, updating: { onSettled: "idle", on: { cancel: (_, { runner }) => { runner.abortAll(); } } } } }); } //#endregion export { createSourceBufferActor }; //# sourceMappingURL=source-buffer.js.map