hls.js 1.6.0-beta.4.0.canary.11043 → 1.6.0-beta.4.0.canary.11045
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hls.d.mts +3 -1
- package/dist/hls.d.ts +3 -1
- package/dist/hls.js +179 -151
- package/dist/hls.js.d.ts +3 -1
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +21 -17
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +21 -17
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +132 -101
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +2 -2
- package/src/controller/base-stream-controller.ts +63 -53
- package/src/controller/buffer-controller.ts +2 -3
- package/src/controller/interstitial-player.ts +6 -3
- package/src/controller/interstitials-controller.ts +51 -27
- package/src/controller/interstitials-schedule.ts +21 -12
- package/src/controller/subtitle-stream-controller.ts +15 -14
- package/src/utils/level-helper.ts +6 -9
@@ -295,6 +295,7 @@ export default class BaseStreamController
|
|
295
295
|
this.media = this.mediaBuffer = null;
|
296
296
|
this.loopSn = undefined;
|
297
297
|
if (transferringMedia) {
|
298
|
+
this.resetLoadingState();
|
298
299
|
this.resetTransmuxer();
|
299
300
|
return;
|
300
301
|
}
|
@@ -448,67 +449,16 @@ export default class BaseStreamController
|
|
448
449
|
}
|
449
450
|
|
450
451
|
protected loadFragment(
|
451
|
-
frag:
|
452
|
+
frag: MediaFragment,
|
452
453
|
level: Level,
|
453
454
|
targetBufferTime: number,
|
454
455
|
) {
|
455
|
-
const config = this.hls.config;
|
456
|
-
if (
|
457
|
-
__USE_INTERSTITIALS__ &&
|
458
|
-
config.interstitialsController &&
|
459
|
-
config.enableInterstitialPlayback !== false &&
|
460
|
-
frag.type !== PlaylistLevelType.SUBTITLE
|
461
|
-
) {
|
462
|
-
// Do not load fragments outside the buffering schedule segment
|
463
|
-
const interstitials = this.hls.interstitialsManager;
|
464
|
-
const bufferingItem = interstitials?.bufferingItem;
|
465
|
-
if (bufferingItem) {
|
466
|
-
const bufferingInterstitial = bufferingItem.event;
|
467
|
-
if (bufferingInterstitial) {
|
468
|
-
// Do not stream fragments while buffering Interstitial Events (except for overlap at the start)
|
469
|
-
if (
|
470
|
-
bufferingInterstitial.appendInPlace ||
|
471
|
-
Math.abs(frag.start - bufferingItem.start) > 1 ||
|
472
|
-
bufferingItem.start === 0
|
473
|
-
) {
|
474
|
-
return;
|
475
|
-
}
|
476
|
-
} else {
|
477
|
-
// Limit fragment loading to media in schedule item
|
478
|
-
if (
|
479
|
-
frag.end <= bufferingItem.start &&
|
480
|
-
level.details?.live === false
|
481
|
-
) {
|
482
|
-
// fragment ends by schedule item start
|
483
|
-
return;
|
484
|
-
}
|
485
|
-
if (frag.start > bufferingItem.end && bufferingItem.nextEvent) {
|
486
|
-
// fragment is past schedule item end
|
487
|
-
return;
|
488
|
-
}
|
489
|
-
}
|
490
|
-
}
|
491
|
-
// Skip loading of fragments that overlap completely with appendInPlace interstitials
|
492
|
-
const playerQueue = interstitials?.playerQueue;
|
493
|
-
if (playerQueue) {
|
494
|
-
for (let i = playerQueue.length; i--; ) {
|
495
|
-
const interstitial = playerQueue[i].interstitial;
|
496
|
-
if (
|
497
|
-
interstitial.appendInPlace &&
|
498
|
-
frag.start >= interstitial.startTime &&
|
499
|
-
frag.end <= interstitial.resumeTime
|
500
|
-
) {
|
501
|
-
return;
|
502
|
-
}
|
503
|
-
}
|
504
|
-
}
|
505
|
-
}
|
506
456
|
this.startFragRequested = true;
|
507
457
|
this._loadFragForPlayback(frag, level, targetBufferTime);
|
508
458
|
}
|
509
459
|
|
510
460
|
private _loadFragForPlayback(
|
511
|
-
fragment:
|
461
|
+
fragment: MediaFragment,
|
512
462
|
level: Level,
|
513
463
|
targetBufferTime: number,
|
514
464
|
) {
|
@@ -1352,6 +1302,7 @@ export default class BaseStreamController
|
|
1352
1302
|
frag = this.getFragmentAtPosition(pos, end, levelDetails);
|
1353
1303
|
}
|
1354
1304
|
|
1305
|
+
frag = this.filterReplacedPrimary(frag, levelDetails);
|
1355
1306
|
return this.mapToInitFragWhenRequired(frag);
|
1356
1307
|
}
|
1357
1308
|
|
@@ -1402,6 +1353,65 @@ export default class BaseStreamController
|
|
1402
1353
|
return nextFragment;
|
1403
1354
|
}
|
1404
1355
|
|
1356
|
+
filterReplacedPrimary(
|
1357
|
+
frag: MediaFragment | null,
|
1358
|
+
details: LevelDetails | undefined,
|
1359
|
+
): MediaFragment | null {
|
1360
|
+
if (!frag) {
|
1361
|
+
return frag;
|
1362
|
+
}
|
1363
|
+
const config = this.hls.config;
|
1364
|
+
if (
|
1365
|
+
__USE_INTERSTITIALS__ &&
|
1366
|
+
config.interstitialsController &&
|
1367
|
+
config.enableInterstitialPlayback !== false &&
|
1368
|
+
frag.type !== PlaylistLevelType.SUBTITLE
|
1369
|
+
) {
|
1370
|
+
// Do not load fragments outside the buffering schedule segment
|
1371
|
+
const interstitials = this.hls.interstitialsManager;
|
1372
|
+
const bufferingItem = interstitials?.bufferingItem;
|
1373
|
+
if (bufferingItem) {
|
1374
|
+
const bufferingInterstitial = bufferingItem.event;
|
1375
|
+
if (bufferingInterstitial) {
|
1376
|
+
// Do not stream fragments while buffering Interstitial Events (except for overlap at the start)
|
1377
|
+
if (
|
1378
|
+
bufferingInterstitial.appendInPlace ||
|
1379
|
+
Math.abs(frag.start - bufferingItem.start) > 1 ||
|
1380
|
+
bufferingItem.start === 0
|
1381
|
+
) {
|
1382
|
+
return null;
|
1383
|
+
}
|
1384
|
+
} else {
|
1385
|
+
// Limit fragment loading to media in schedule item
|
1386
|
+
if (frag.end <= bufferingItem.start && details?.live === false) {
|
1387
|
+
// fragment ends by schedule item start
|
1388
|
+
// this.fragmentTracker.fragBuffered(frag, true);
|
1389
|
+
return null;
|
1390
|
+
}
|
1391
|
+
if (frag.start > bufferingItem.end && bufferingItem.nextEvent) {
|
1392
|
+
// fragment is past schedule item end
|
1393
|
+
return null;
|
1394
|
+
}
|
1395
|
+
}
|
1396
|
+
}
|
1397
|
+
// Skip loading of fragments that overlap completely with appendInPlace interstitials
|
1398
|
+
const playerQueue = interstitials?.playerQueue;
|
1399
|
+
if (playerQueue) {
|
1400
|
+
for (let i = playerQueue.length; i--; ) {
|
1401
|
+
const interstitial = playerQueue[i].interstitial;
|
1402
|
+
if (
|
1403
|
+
interstitial.appendInPlace &&
|
1404
|
+
frag.start >= interstitial.startTime &&
|
1405
|
+
frag.end <= interstitial.resumeTime
|
1406
|
+
) {
|
1407
|
+
return null;
|
1408
|
+
}
|
1409
|
+
}
|
1410
|
+
}
|
1411
|
+
}
|
1412
|
+
return frag;
|
1413
|
+
}
|
1414
|
+
|
1405
1415
|
mapToInitFragWhenRequired(frag: Fragment | null): typeof frag {
|
1406
1416
|
// If an initSegment is present, it must be buffered first
|
1407
1417
|
if (frag?.initSegment && !frag?.initSegment.data && !this.bitrateTest) {
|
@@ -1486,6 +1486,8 @@ transfer tracks: ${stringify(transferredTracks, (key, value) => (key === 'initSe
|
|
1486
1486
|
if (!media || !mediaSource) {
|
1487
1487
|
return;
|
1488
1488
|
}
|
1489
|
+
// once received, don't listen anymore to sourceopen event
|
1490
|
+
mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);
|
1489
1491
|
media.removeEventListener('emptied', this._onMediaEmptied);
|
1490
1492
|
this.updateDuration();
|
1491
1493
|
this.hls.trigger(Events.MEDIA_ATTACHED, {
|
@@ -1493,9 +1495,6 @@ transfer tracks: ${stringify(transferredTracks, (key, value) => (key === 'initSe
|
|
1493
1495
|
mediaSource: mediaSource as MediaSource,
|
1494
1496
|
});
|
1495
1497
|
|
1496
|
-
// once received, don't listen anymore to sourceopen event
|
1497
|
-
mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);
|
1498
|
-
|
1499
1498
|
if (this.mediaSource !== null) {
|
1500
1499
|
this.checkPendingTracks();
|
1501
1500
|
}
|
@@ -27,6 +27,7 @@ export class HlsAssetPlayer {
|
|
27
27
|
public tracks: Partial<BufferCodecsData> | null = null;
|
28
28
|
private hasDetails: boolean = false;
|
29
29
|
private mediaAttached: HTMLMediaElement | null = null;
|
30
|
+
private _currentTime?: number;
|
30
31
|
|
31
32
|
constructor(
|
32
33
|
HlsPlayerClass: typeof Hls,
|
@@ -89,7 +90,7 @@ export class HlsAssetPlayer {
|
|
89
90
|
get bufferedEnd(): number {
|
90
91
|
const media = this.media || this.mediaAttached;
|
91
92
|
if (!media) {
|
92
|
-
return
|
93
|
+
return this.currentTime;
|
93
94
|
}
|
94
95
|
const bufferInfo = BufferHelper.bufferInfo(media, media.currentTime, 0.001);
|
95
96
|
return this.getAssetTime(bufferInfo.end);
|
@@ -98,7 +99,7 @@ export class HlsAssetPlayer {
|
|
98
99
|
get currentTime(): number {
|
99
100
|
const media = this.media || this.mediaAttached;
|
100
101
|
if (!media) {
|
101
|
-
return 0;
|
102
|
+
return this._currentTime || 0;
|
102
103
|
}
|
103
104
|
return this.getAssetTime(media.currentTime);
|
104
105
|
}
|
@@ -151,6 +152,7 @@ export class HlsAssetPlayer {
|
|
151
152
|
private removeMediaListeners() {
|
152
153
|
const media = this.mediaAttached;
|
153
154
|
if (media) {
|
155
|
+
this._currentTime = media.currentTime;
|
154
156
|
media.removeEventListener('timeupdate', this.checkPlayout);
|
155
157
|
}
|
156
158
|
}
|
@@ -170,6 +172,7 @@ export class HlsAssetPlayer {
|
|
170
172
|
|
171
173
|
detachMedia() {
|
172
174
|
this.removeMediaListeners();
|
175
|
+
this.mediaAttached = null;
|
173
176
|
this.hls.detachMedia();
|
174
177
|
}
|
175
178
|
|
@@ -210,6 +213,6 @@ export class HlsAssetPlayer {
|
|
210
213
|
}
|
211
214
|
|
212
215
|
toString(): string {
|
213
|
-
return `HlsAssetPlayer: ${eventAssetToString(this.assetItem)} ${this.hls
|
216
|
+
return `HlsAssetPlayer: ${eventAssetToString(this.assetItem)} ${this.hls?.sessionId} ${this.interstitial?.appendInPlace ? 'append-in-place' : ''}`;
|
214
217
|
}
|
215
218
|
}
|
@@ -195,11 +195,11 @@ export default class InterstitialsController
|
|
195
195
|
}
|
196
196
|
|
197
197
|
resumeBuffering() {
|
198
|
-
this.
|
198
|
+
this.getBufferingPlayer()?.resumeBuffering();
|
199
199
|
}
|
200
200
|
|
201
201
|
pauseBuffering() {
|
202
|
-
this.
|
202
|
+
this.getBufferingPlayer()?.pauseBuffering();
|
203
203
|
}
|
204
204
|
|
205
205
|
destroy() {
|
@@ -760,6 +760,9 @@ export default class InterstitialsController
|
|
760
760
|
player: Hls | HlsAssetPlayer,
|
761
761
|
media: HTMLMediaElement,
|
762
762
|
) {
|
763
|
+
if (player.media === media) {
|
764
|
+
return;
|
765
|
+
}
|
763
766
|
let attachMediaSourceData: MediaAttachingData | null = null;
|
764
767
|
const primaryPlayer = this.hls;
|
765
768
|
const isAssetPlayer = player !== primaryPlayer;
|
@@ -768,32 +771,44 @@ export default class InterstitialsController
|
|
768
771
|
const detachedMediaSource = this.detachedData?.mediaSource;
|
769
772
|
|
770
773
|
let logFromSource: string;
|
771
|
-
if (primaryPlayer.media
|
772
|
-
|
773
|
-
|
774
|
+
if (primaryPlayer.media) {
|
775
|
+
if (appendInPlace) {
|
776
|
+
attachMediaSourceData = primaryPlayer.transferMedia();
|
777
|
+
this.detachedData = attachMediaSourceData;
|
778
|
+
}
|
774
779
|
logFromSource = `Primary`;
|
775
780
|
} else if (detachedMediaSource) {
|
776
781
|
const bufferingPlayer = this.getBufferingPlayer();
|
777
782
|
if (bufferingPlayer) {
|
778
783
|
attachMediaSourceData = bufferingPlayer.transferMedia();
|
784
|
+
logFromSource = `${bufferingPlayer}`;
|
785
|
+
} else {
|
786
|
+
logFromSource = `detached MediaSource`;
|
779
787
|
}
|
780
|
-
logFromSource = `${bufferingPlayer}`;
|
781
788
|
} else {
|
782
|
-
logFromSource =
|
789
|
+
logFromSource = `detached media`;
|
783
790
|
}
|
784
|
-
this.log(
|
785
|
-
`transferring to ${isAssetPlayer ? player : 'Primary'}
|
786
|
-
MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
|
787
|
-
);
|
788
|
-
|
789
791
|
if (!attachMediaSourceData) {
|
790
792
|
if (detachedMediaSource) {
|
791
793
|
attachMediaSourceData = this.detachedData;
|
792
794
|
this.log(
|
793
795
|
`using detachedData: MediaSource ${stringify(attachMediaSourceData)}`,
|
794
796
|
);
|
795
|
-
} else if (!this.detachedData ||
|
796
|
-
//
|
797
|
+
} else if (!this.detachedData || primaryPlayer.media === media) {
|
798
|
+
// Keep interstitial media transition consistent
|
799
|
+
const playerQueue = this.playerQueue;
|
800
|
+
if (playerQueue.length > 1) {
|
801
|
+
playerQueue.forEach((queuedPlayer) => {
|
802
|
+
if (
|
803
|
+
isAssetPlayer &&
|
804
|
+
queuedPlayer.interstitial.appendInPlace !== appendInPlace
|
805
|
+
) {
|
806
|
+
const interstitial = queuedPlayer.interstitial;
|
807
|
+
this.clearInterstitial(queuedPlayer.interstitial, null);
|
808
|
+
interstitial.appendInPlace = false;
|
809
|
+
}
|
810
|
+
});
|
811
|
+
}
|
797
812
|
this.hls.detachMedia();
|
798
813
|
this.detachedData = { media };
|
799
814
|
}
|
@@ -807,7 +822,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
807
822
|
this.log(
|
808
823
|
`${transferring ? 'transfering MediaSource' : 'attaching media'} to ${
|
809
824
|
isAssetPlayer ? player : 'Primary'
|
810
|
-
}`,
|
825
|
+
} from ${logFromSource}`,
|
811
826
|
);
|
812
827
|
if (dataToAttach === attachMediaSourceData) {
|
813
828
|
const isAssetAtEndOfSchedule =
|
@@ -1068,7 +1083,7 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1068
1083
|
player,
|
1069
1084
|
});
|
1070
1085
|
this.retreiveMediaSource(assetId, scheduledItem);
|
1071
|
-
if (player.media && !this.detachedData) {
|
1086
|
+
if (player.media && !this.detachedData?.mediaSource) {
|
1072
1087
|
player.detachMedia();
|
1073
1088
|
}
|
1074
1089
|
}
|
@@ -1414,7 +1429,10 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1414
1429
|
main,
|
1415
1430
|
};
|
1416
1431
|
this.mediaSelection = currentSelection;
|
1417
|
-
this.schedule.parseInterstitialDateRanges(
|
1432
|
+
this.schedule.parseInterstitialDateRanges(
|
1433
|
+
currentSelection,
|
1434
|
+
this.hls.config.interstitialAppendInPlace,
|
1435
|
+
);
|
1418
1436
|
|
1419
1437
|
if (!this.effectivePlayingItem && this.schedule.items) {
|
1420
1438
|
this.checkStart();
|
@@ -1532,6 +1550,8 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1532
1550
|
if (!this.playingLastItem && playingItem) {
|
1533
1551
|
const playingIndex = this.findItemIndex(playingItem);
|
1534
1552
|
this.setSchedulePosition(playingIndex + 1);
|
1553
|
+
} else {
|
1554
|
+
this.shouldPlay = false;
|
1535
1555
|
}
|
1536
1556
|
}
|
1537
1557
|
|
@@ -1552,9 +1572,6 @@ MediaSource ${stringify(attachMediaSourceData)} from ${logFromSource}`,
|
|
1552
1572
|
interstitialEvents.length || removedIds.length
|
1553
1573
|
);
|
1554
1574
|
if (interstitialsUpdated) {
|
1555
|
-
if (this.hls.config.interstitialAppendInPlace === false) {
|
1556
|
-
interstitialEvents.forEach((event) => (event.appendInPlace = false));
|
1557
|
-
}
|
1558
1575
|
this.log(
|
1559
1576
|
`INTERSTITIALS_UPDATED (${
|
1560
1577
|
interstitialEvents.length
|
@@ -1888,18 +1905,18 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
1888
1905
|
interstitial: InterstitialEvent,
|
1889
1906
|
assetListIndex: number,
|
1890
1907
|
): HlsAssetPlayer | null {
|
1908
|
+
const uri = interstitial.assetUrl;
|
1891
1909
|
const assetListLength = interstitial.assetList.length;
|
1892
1910
|
const neverLoaded = assetListLength === 0 && !interstitial.assetListLoader;
|
1893
1911
|
const playOnce = interstitial.cue.once;
|
1894
1912
|
if (neverLoaded) {
|
1895
1913
|
this.log(
|
1896
|
-
`Load interstitial asset ${assetListIndex + 1}/${assetListLength} ${interstitial}`,
|
1914
|
+
`Load interstitial asset ${assetListIndex + 1}/${uri ? 1 : assetListLength} ${interstitial}`,
|
1897
1915
|
);
|
1898
1916
|
const timelineStart = interstitial.timelineStart;
|
1899
1917
|
if (interstitial.appendInPlace) {
|
1900
1918
|
this.flushFrontBuffer(timelineStart + 0.25);
|
1901
1919
|
}
|
1902
|
-
const uri = interstitial.assetUrl;
|
1903
1920
|
if (uri) {
|
1904
1921
|
return this.createAsset(
|
1905
1922
|
interstitial,
|
@@ -2288,9 +2305,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
2288
2305
|
}
|
2289
2306
|
|
2290
2307
|
// detach media and attach to interstitial player if it does not have another element attached
|
2291
|
-
|
2292
|
-
this.bufferAssetPlayer(player, media);
|
2293
|
-
}
|
2308
|
+
this.bufferAssetPlayer(player, media);
|
2294
2309
|
}
|
2295
2310
|
|
2296
2311
|
private bufferAssetPlayer(player: HlsAssetPlayer, media: HTMLMediaElement) {
|
@@ -2306,11 +2321,19 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
2306
2321
|
if (bufferingPlayer === player) {
|
2307
2322
|
return;
|
2308
2323
|
}
|
2324
|
+
const appendInPlaceNext = interstitial.appendInPlace;
|
2325
|
+
if (
|
2326
|
+
appendInPlaceNext &&
|
2327
|
+
bufferingPlayer?.interstitial.appendInPlace === false
|
2328
|
+
) {
|
2329
|
+
// Media is detached and not available to append in place
|
2330
|
+
return;
|
2331
|
+
}
|
2309
2332
|
const activeTracks =
|
2310
2333
|
bufferingPlayer?.tracks ||
|
2311
2334
|
this.detachedData?.tracks ||
|
2312
2335
|
this.requiredTracks;
|
2313
|
-
if (
|
2336
|
+
if (appendInPlaceNext && assetItem !== this.playingAsset) {
|
2314
2337
|
// Do not buffer another item if tracks are unknown or incompatible
|
2315
2338
|
if (!player.tracks) {
|
2316
2339
|
return;
|
@@ -2411,7 +2434,6 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
2411
2434
|
} error: ${interstitial.error}`,
|
2412
2435
|
);
|
2413
2436
|
if (interstitial.appendInPlace) {
|
2414
|
-
interstitial.appendInPlace = false;
|
2415
2437
|
this.attachPrimary(flushStart, null);
|
2416
2438
|
this.flushFrontBuffer(flushStart);
|
2417
2439
|
}
|
@@ -2423,6 +2445,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))}`,
|
|
2423
2445
|
if (!this.itemsMatch(playingItem, newPlayingItem)) {
|
2424
2446
|
const scheduleIndex = this.schedule.findItemIndexAtTime(timelinePos);
|
2425
2447
|
this.setSchedulePosition(scheduleIndex);
|
2448
|
+
} else {
|
2449
|
+
this.clearInterstitial(interstitial, null);
|
2426
2450
|
}
|
2427
2451
|
} else {
|
2428
2452
|
this.checkStart();
|
@@ -239,13 +239,20 @@ export class InterstitialsSchedule extends Logger {
|
|
239
239
|
return null;
|
240
240
|
}
|
241
241
|
|
242
|
-
public parseInterstitialDateRanges(
|
242
|
+
public parseInterstitialDateRanges(
|
243
|
+
mediaSelection: MediaSelection,
|
244
|
+
enableAppendInPlace: boolean,
|
245
|
+
) {
|
243
246
|
const details = mediaSelection.main.details!;
|
244
247
|
const { dateRanges } = details;
|
245
248
|
const previousInterstitialEvents = this.events;
|
246
|
-
const interstitialEvents = this.parseDateRanges(
|
247
|
-
|
248
|
-
|
249
|
+
const interstitialEvents = this.parseDateRanges(
|
250
|
+
dateRanges,
|
251
|
+
{
|
252
|
+
url: details.url,
|
253
|
+
},
|
254
|
+
enableAppendInPlace,
|
255
|
+
);
|
249
256
|
const ids = Object.keys(dateRanges);
|
250
257
|
const removedInterstitials = previousInterstitialEvents
|
251
258
|
? previousInterstitialEvents.filter(
|
@@ -321,6 +328,7 @@ export class InterstitialsSchedule extends Logger {
|
|
321
328
|
private parseDateRanges(
|
322
329
|
dateRanges: Record<string, DateRange>,
|
323
330
|
baseData: BaseData,
|
331
|
+
enableAppendInPlace: boolean,
|
324
332
|
): InterstitialEvent[] {
|
325
333
|
const interstitialEvents: InterstitialEvent[] = [];
|
326
334
|
const ids = Object.keys(dateRanges);
|
@@ -336,6 +344,9 @@ export class InterstitialsSchedule extends Logger {
|
|
336
344
|
} else {
|
337
345
|
interstitial = new InterstitialEvent(dateRange, baseData);
|
338
346
|
this.eventMap[id] = interstitial;
|
347
|
+
if (enableAppendInPlace === false) {
|
348
|
+
interstitial.appendInPlace = enableAppendInPlace;
|
349
|
+
}
|
339
350
|
}
|
340
351
|
interstitialEvents.push(interstitial);
|
341
352
|
}
|
@@ -570,15 +581,13 @@ export class InterstitialsSchedule extends Logger {
|
|
570
581
|
interstitial.appendInPlace = false;
|
571
582
|
}
|
572
583
|
}
|
573
|
-
if (!interstitial.appendInPlace) {
|
584
|
+
if (!interstitial.appendInPlace && i + 1 < interstitialEvents.length) {
|
574
585
|
// abutting Interstitials must use the same MediaSource strategy, this applies to all whether or not they are back to back:
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
interstitialEvents[j].appendInPlace = false;
|
581
|
-
}
|
586
|
+
const timeBetween =
|
587
|
+
interstitialEvents[i + 1].startTime -
|
588
|
+
interstitialEvents[i].resumeTime;
|
589
|
+
if (timeBetween < ABUTTING_THRESHOLD_SECONDS) {
|
590
|
+
interstitialEvents[i + 1].appendInPlace = false;
|
582
591
|
}
|
583
592
|
}
|
584
593
|
// Update cumulativeDuration for next abutting interstitial with the same start date
|
@@ -447,7 +447,7 @@ export class SubtitleStreamController
|
|
447
447
|
const fragLen = fragments.length;
|
448
448
|
const end = trackDetails.edge;
|
449
449
|
|
450
|
-
let foundFrag:
|
450
|
+
let foundFrag: MediaFragment | null = null;
|
451
451
|
const fragPrevious = this.fragPrevious;
|
452
452
|
if (targetBufferTime < end) {
|
453
453
|
const tolerance = config.maxFragLookUpTolerance;
|
@@ -469,27 +469,28 @@ export class SubtitleStreamController
|
|
469
469
|
} else {
|
470
470
|
foundFrag = fragments[fragLen - 1];
|
471
471
|
}
|
472
|
+
foundFrag = this.filterReplacedPrimary(foundFrag, track.details);
|
472
473
|
if (!foundFrag) {
|
473
474
|
return;
|
474
475
|
}
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
) {
|
485
|
-
foundFrag = prevFrag;
|
486
|
-
}
|
476
|
+
// Load earlier fragment in same discontinuity to make up for misaligned playlists and cues that extend beyond end of segment
|
477
|
+
const curSNIdx = foundFrag.sn - trackDetails.startSN;
|
478
|
+
const prevFrag = fragments[curSNIdx - 1];
|
479
|
+
if (
|
480
|
+
prevFrag &&
|
481
|
+
prevFrag.cc === foundFrag.cc &&
|
482
|
+
this.fragmentTracker.getState(prevFrag) === FragmentState.NOT_LOADED
|
483
|
+
) {
|
484
|
+
foundFrag = prevFrag;
|
487
485
|
}
|
488
486
|
if (
|
489
487
|
this.fragmentTracker.getState(foundFrag) === FragmentState.NOT_LOADED
|
490
488
|
) {
|
491
489
|
// only load if fragment is not loaded
|
492
|
-
this.
|
490
|
+
const fragToLoad = this.mapToInitFragWhenRequired(foundFrag);
|
491
|
+
if (fragToLoad) {
|
492
|
+
this.loadFragment(fragToLoad, track, targetBufferTime);
|
493
|
+
}
|
493
494
|
}
|
494
495
|
}
|
495
496
|
}
|
@@ -536,14 +536,11 @@ export function findPart(
|
|
536
536
|
|
537
537
|
export function reassignFragmentLevelIndexes(levels: Level[]) {
|
538
538
|
levels.forEach((level, index) => {
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
fragment.level = index;
|
543
|
-
|
544
|
-
|
545
|
-
}
|
546
|
-
});
|
547
|
-
}
|
539
|
+
level.details?.fragments.forEach((fragment) => {
|
540
|
+
fragment.level = index;
|
541
|
+
if (fragment.initSegment) {
|
542
|
+
fragment.initSegment.level = index;
|
543
|
+
}
|
544
|
+
});
|
548
545
|
});
|
549
546
|
}
|