UNPKG

p2p-media-loader-shaka

Version:

P2P Media Loader Shaka Player integration

133 lines 5.08 kB
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