From fb9ed3ed073c21948a93bf49c1baca7ce76eb8e0 Mon Sep 17 00:00:00 2001 From: Igor Zolotarenko Date: Mon, 18 Dec 2023 20:07:27 +0200 Subject: [PATCH] Fix bug. --- .../p2p-media-loader-core/src/linked-map.ts | 9 +++ packages/p2p-media-loader-core/src/types.d.ts | 2 +- .../src/segment-manager.ts | 60 ++++++++++++------- .../src/stream-utils.ts | 9 ++- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/packages/p2p-media-loader-core/src/linked-map.ts b/packages/p2p-media-loader-core/src/linked-map.ts index f1827daf..3af745ec 100644 --- a/packages/p2p-media-loader-core/src/linked-map.ts +++ b/packages/p2p-media-loader-core/src/linked-map.ts @@ -68,6 +68,15 @@ export class LinkedMap { } } + *valuesBackwards(key?: K) { + let value = key ? this.map.get(key) : this._last; + if (value === undefined) return; + while (value?.item !== undefined) { + yield value.item[1]; + value = value.prev; + } + } + *keys(): Generator { let value = this._first; if (value === undefined) return; diff --git a/packages/p2p-media-loader-core/src/types.d.ts b/packages/p2p-media-loader-core/src/types.d.ts index d555a881..e03ab496 100644 --- a/packages/p2p-media-loader-core/src/types.d.ts +++ b/packages/p2p-media-loader-core/src/types.d.ts @@ -26,7 +26,7 @@ export type Stream = { export type ReadonlyLinkedMap = Pick< LinkedMap, - "has" | "keys" | "values" | "size" + "has" | "keys" | "values" | "valuesBackwards" | "size" >; export type StreamWithSegments< diff --git a/packages/p2p-media-loader-shaka/src/segment-manager.ts b/packages/p2p-media-loader-shaka/src/segment-manager.ts index 2a3c2185..870b56a5 100644 --- a/packages/p2p-media-loader-shaka/src/segment-manager.ts +++ b/packages/p2p-media-loader-shaka/src/segment-manager.ts @@ -5,6 +5,7 @@ import { StreamWithReadonlySegments, SegmentBase, StreamType, + ReadonlyLinkedMap, } from "p2p-media-loader-core"; export class SegmentManager { @@ -72,6 +73,7 @@ export class SegmentManager { staleSegmentsIds.delete(segmentLocalId); } + if (!newSegments.length && !staleSegmentsIds.size) return; this.core.updateStream(managerStream.localId, newSegments, [ ...staleSegmentsIds, ]); @@ -81,52 +83,66 @@ export class SegmentManager { managerStream: StreamWithReadonlySegments, segmentReferences: shaka.media.SegmentReference[] ) { - const segments = [...managerStream.segments.values()]; + const { segments } = managerStream; const lastMediaSequence = Utils.getStreamLastMediaSequence(managerStream); const newSegments: SegmentBase[] = []; - if (segments.length === 0) { + if (segments.size === 0) { const firstReferenceMediaSequence = lastMediaSequence === undefined ? 0 : lastMediaSequence - segmentReferences.length + 1; - segmentReferences.forEach((reference, index) => { + + for (const [index, reference] of segmentReferences.entries()) { const segment = Utils.createSegment({ segmentReference: reference, externalId: firstReferenceMediaSequence + index, }); newSegments.push(segment); - }); + } this.core.updateStream(managerStream.localId, newSegments); return; } - let index = lastMediaSequence ?? 0; - const startSize = managerStream.segments.size; + if (!lastMediaSequence) return; + let mediaSequence = lastMediaSequence; - for (let i = segmentReferences.length - 1; i >= 0; i--) { - const reference = segmentReferences[i]; + for (const reference of itemsBackwards(segmentReferences)) { const localId = Utils.getSegmentLocalIdFromReference(reference); - if (!managerStream.segments.has(localId)) { - const segment = Utils.createSegment({ - localId, - segmentReference: reference, - externalId: index, - }); - newSegments.push(segment); - index--; - } else { - break; - } + if (segments.has(localId)) break; + const segment = Utils.createSegment({ + localId, + segmentReference: reference, + externalId: mediaSequence, + }); + newSegments.push(segment); + mediaSequence--; } newSegments.reverse(); - const deleteCount = managerStream.segments.size - startSize; const staleSegmentIds: string[] = []; - for (let i = 0; i < deleteCount; i++) { - const segment = segments[i]; + const amountToDelete = newSegments.length; + for (const segment of nSegmentsBackwards(segments, amountToDelete)) { staleSegmentIds.push(segment.localId); } + + if (!newSegments.length && !staleSegmentIds.length) return; this.core.updateStream(managerStream.localId, newSegments, staleSegmentIds); } } + +function* itemsBackwards(items: T[]) { + for (let i = items.length - 1; i >= 0; i--) yield items[i]; +} + +function* nSegmentsBackwards( + segments: ReadonlyLinkedMap, + amount: number +) { + let i = 0; + for (const segment of segments.valuesBackwards()) { + if (i >= amount) break; + yield segment; + i--; + } +} diff --git a/packages/p2p-media-loader-shaka/src/stream-utils.ts b/packages/p2p-media-loader-shaka/src/stream-utils.ts index a0a955a1..4a84c8a7 100644 --- a/packages/p2p-media-loader-shaka/src/stream-utils.ts +++ b/packages/p2p-media-loader-shaka/src/stream-utils.ts @@ -80,10 +80,9 @@ export function getStreamLastMediaSequence( ): number | undefined { const { shakaStream } = stream; const map = shakaStream.mediaSequenceTimeMap; + if (!map) return; - if (map) { - const firstMediaSequence = map.keys().next().value as number | undefined; - if (firstMediaSequence === undefined) return; - return firstMediaSequence + map.size - 1; - } + const firstMediaSequence = map.keys().next().value as number | undefined; + if (firstMediaSequence === undefined) return; + return firstMediaSequence + map.size - 1; }