@@ -255,6 +255,17 @@ export default class BaseStreamController
255
255
}
256
256
}
257
257
258
+ protected get timelineOffset ( ) : number {
259
+ const configuredTimelineOffset = this . config . timelineOffset ;
260
+ if ( configuredTimelineOffset ) {
261
+ return (
262
+ this . getLevelDetails ( ) ?. appliedTimelineOffset ||
263
+ configuredTimelineOffset
264
+ ) ;
265
+ }
266
+ return 0 ;
267
+ }
268
+
258
269
protected onMediaAttached (
259
270
event : Events . MEDIA_ATTACHED ,
260
271
data : MediaAttachedData ,
@@ -1299,9 +1310,8 @@ export default class BaseStreamController
1299
1310
: levelDetails . fragmentEnd ;
1300
1311
frag = this . getFragmentAtPosition ( pos , end , levelDetails ) ;
1301
1312
}
1302
-
1303
- frag = this . filterReplacedPrimary ( frag , levelDetails ) ;
1304
- return this . mapToInitFragWhenRequired ( frag ) ;
1313
+ const programFrag = this . filterReplacedPrimary ( frag , levelDetails ) ;
1314
+ return this . mapToInitFragWhenRequired ( programFrag ) ;
1305
1315
}
1306
1316
1307
1317
protected isLoopLoading ( frag : Fragment , targetBufferTime : number ) : boolean {
@@ -1351,18 +1361,26 @@ export default class BaseStreamController
1351
1361
return nextFragment ;
1352
1362
}
1353
1363
1354
- filterReplacedPrimary (
1364
+ protected get primaryPrefetch ( ) : boolean {
1365
+ if ( interstitialsEnabled ( this . hls . config ) ) {
1366
+ const playingInterstitial =
1367
+ this . hls . interstitialsManager ?. playingItem ?. event ;
1368
+ if ( playingInterstitial ) {
1369
+ return true ;
1370
+ }
1371
+ }
1372
+ return false ;
1373
+ }
1374
+
1375
+ protected filterReplacedPrimary (
1355
1376
frag : MediaFragment | null ,
1356
1377
details : LevelDetails | undefined ,
1357
1378
) : MediaFragment | null {
1358
1379
if ( ! frag ) {
1359
1380
return frag ;
1360
1381
}
1361
- const config = this . hls . config ;
1362
1382
if (
1363
- __USE_INTERSTITIALS__ &&
1364
- config . interstitialsController &&
1365
- config . enableInterstitialPlayback !== false &&
1383
+ interstitialsEnabled ( this . hls . config ) &&
1366
1384
frag . type !== PlaylistLevelType . SUBTITLE
1367
1385
) {
1368
1386
// Do not load fragments outside the buffering schedule segment
@@ -1388,7 +1406,13 @@ export default class BaseStreamController
1388
1406
}
1389
1407
if ( frag . start > bufferingItem . end && bufferingItem . nextEvent ) {
1390
1408
// fragment is past schedule item end
1391
- return null ;
1409
+ // allow some overflow when not appending in place to prevent stalls
1410
+ if (
1411
+ bufferingItem . nextEvent . appendInPlace ||
1412
+ frag . start - bufferingItem . end > 1
1413
+ ) {
1414
+ return null ;
1415
+ }
1392
1416
}
1393
1417
}
1394
1418
}
@@ -1659,6 +1683,7 @@ export default class BaseStreamController
1659
1683
if ( startPosition < sliding ) {
1660
1684
startPosition = - 1 ;
1661
1685
}
1686
+ const timelineOffset = this . timelineOffset ;
1662
1687
if ( startPosition === - 1 ) {
1663
1688
// Use Playlist EXT-X-START:TIME-OFFSET when set
1664
1689
// Prioritize Multivariant Playlist offset so that main, audio, and subtitle stream-controller start times match
@@ -1693,9 +1718,9 @@ export default class BaseStreamController
1693
1718
this . log ( `setting startPosition to 0 by default` ) ;
1694
1719
this . startPosition = startPosition = 0 ;
1695
1720
}
1696
- this . lastCurrentTime = startPosition ;
1721
+ this . lastCurrentTime = startPosition + timelineOffset ;
1697
1722
}
1698
- this . nextLoadPosition = startPosition ;
1723
+ this . nextLoadPosition = startPosition + timelineOffset ;
1699
1724
}
1700
1725
1701
1726
protected getLoadPosition ( ) : number {
@@ -2066,3 +2091,11 @@ export default class BaseStreamController
2066
2091
return this . _state ;
2067
2092
}
2068
2093
}
2094
+
2095
+ function interstitialsEnabled ( config : HlsConfig ) : boolean {
2096
+ return (
2097
+ __USE_INTERSTITIALS__ &&
2098
+ ! ! config . interstitialsController &&
2099
+ config . enableInterstitialPlayback !== false
2100
+ ) ;
2101
+ }
0 commit comments