p2p-media-loader-shaka
Version:
P2P Media Loader Shaka Player integration
133 lines • 5.08 kB
JavaScript
import * as Utils from "./stream-utils.js";
// The minimum time interval (in seconds) between segments to assign unique IDs.
// If two segments in the same playlist start within a time frame shorter than this interval,
// they risk being assigned the same ID.
// Such overlapping IDs can lead to potential conflicts or issues in segment processing.
const SEGMENT_ID_RESOLUTION_IN_SECONDS = 0.5;
export class SegmentManager {
constructor(streamInfo, core) {
Object.defineProperty(this, "core", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "streamInfo", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.core = core;
this.streamInfo = streamInfo;
}
setStream(shakaStream, type, index = -1) {
this.core.addStreamIfNoneExists({
runtimeId: shakaStream.id.toString(),
type,
index,
shakaStream,
});
if (shakaStream.segmentIndex)
this.updateStreamSegments(shakaStream);
}
updateStreamSegments(shakaStream, segmentReferences) {
const stream = this.core.getStream(shakaStream.id.toString());
if (!stream)
return;
const { segmentIndex } = stream.shakaStream;
if (!segmentReferences && segmentIndex) {
try {
segmentReferences = [...segmentIndex];
}
catch {
return;
}
}
if (!segmentReferences)
return;
if (this.streamInfo.protocol === "hls") {
this.processHlsSegmentReferences(stream, segmentReferences);
}
else {
this.processDashSegmentReferences(stream, segmentReferences);
}
}
processDashSegmentReferences(managerStream, segmentReferences) {
const staleSegmentsIds = new Set(managerStream.segments.keys());
const newSegments = [];
for (const reference of segmentReferences) {
const externalId = Math.trunc(reference.getStartTime() / SEGMENT_ID_RESOLUTION_IN_SECONDS);
const runtimeId = Utils.getSegmentRuntimeIdFromReference(reference);
if (!managerStream.segments.has(runtimeId)) {
const segment = Utils.createSegment({
segmentReference: reference,
externalId,
runtimeId,
});
newSegments.push(segment);
}
staleSegmentsIds.delete(runtimeId);
}
if (!newSegments.length && !staleSegmentsIds.size)
return;
this.core.updateStream(managerStream.runtimeId, newSegments, staleSegmentsIds.values());
}
processHlsSegmentReferences(managerStream, segmentReferences) {
const { segments } = managerStream;
const lastMediaSequence = Utils.getStreamLastMediaSequence(managerStream);
const newSegments = [];
if (segments.size === 0) {
const firstReferenceMediaSequence = lastMediaSequence === undefined
? 0
: lastMediaSequence - segmentReferences.length + 1;
for (const [index, reference] of segmentReferences.entries()) {
const segment = Utils.createSegment({
segmentReference: reference,
externalId: firstReferenceMediaSequence + index,
});
newSegments.push(segment);
}
this.core.updateStream(managerStream.runtimeId, newSegments);
return;
}
if (!lastMediaSequence)
return;
let mediaSequence = lastMediaSequence;
for (const reference of itemsBackwards(segmentReferences)) {
const runtimeId = Utils.getSegmentRuntimeIdFromReference(reference);
if (segments.has(runtimeId))
break;
const segment = Utils.createSegment({
runtimeId,
segmentReference: reference,
externalId: mediaSequence,
});
newSegments.push(segment);
mediaSequence--;
}
newSegments.reverse();
const staleSegmentIds = [];
const countToDelete = newSegments.length;
for (const segment of nSegmentsBackwards(segments, countToDelete)) {
staleSegmentIds.push(segment.runtimeId);
}
if (!newSegments.length && !staleSegmentIds.length)
return;
this.core.updateStream(managerStream.runtimeId, newSegments, staleSegmentIds);
}
}
function* itemsBackwards(items) {
for (let i = items.length - 1; i >= 0; i--)
yield items[i];
}
function* nSegmentsBackwards(segments, count) {
let i = 0;
for (const segment of segments.values()) {
if (i >= count)
break;
yield segment;
i++;
}
}
//# sourceMappingURL=segment-manager.js.map