Files
v10/dist/dev/playback/actors/dom/source-buffer.js
T

139 lines
4.2 KiB
JavaScript

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