hls.js 1.6.0-beta.1.0.canary.10714 → 1.6.0-beta.1.0.canary.10715
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.js +45 -13
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +45 -13
- 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 +48 -13
- 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 +48 -13
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/package.json +1 -1
- package/src/controller/abr-controller.ts +64 -11
- package/src/controller/level-controller.ts +7 -3
@@ -296,15 +296,18 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
296
296
|
? (stats.loaded * 1000) / timeStreaming
|
297
297
|
: 0;
|
298
298
|
// fragLoadDelay is an estimate of the time (in seconds) it will take to buffer the remainder of the fragment
|
299
|
+
const ttfbSeconds = ttfbEstimate / 1000;
|
299
300
|
const fragLoadedDelay = loadRate
|
300
301
|
? (expectedLen - stats.loaded) / loadRate
|
301
|
-
: (expectedLen * 8) / bwEstimate +
|
302
|
+
: (expectedLen * 8) / bwEstimate + ttfbSeconds;
|
302
303
|
// Only downswitch if the time to finish loading the current fragment is greater than the amount of buffer left
|
303
304
|
if (fragLoadedDelay <= bufferStarvationDelay) {
|
304
305
|
return;
|
305
306
|
}
|
306
307
|
|
307
308
|
const bwe = loadRate ? loadRate * 8 : bwEstimate;
|
309
|
+
const live = this.hls.latestLevelDetails?.live === true;
|
310
|
+
const abrBandWidthUpFactor = this.hls.config.abrBandWidthUpFactor;
|
308
311
|
let fragLevelNextLoadedDelay: number = Number.POSITIVE_INFINITY;
|
309
312
|
let nextLoadLevel: number;
|
310
313
|
// Iterate through lower level and try to find the largest one that avoids rebuffering
|
@@ -316,13 +319,17 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
316
319
|
// compute time to load next fragment at lower level
|
317
320
|
// 8 = bits per byte (bps/Bps)
|
318
321
|
const levelNextBitrate = levels[nextLoadLevel].maxBitrate;
|
322
|
+
const requiresLevelLoad = !levels[nextLoadLevel].details || live;
|
319
323
|
fragLevelNextLoadedDelay = this.getTimeToLoadFrag(
|
320
|
-
|
324
|
+
ttfbSeconds,
|
321
325
|
bwe,
|
322
326
|
duration * levelNextBitrate,
|
323
|
-
|
327
|
+
requiresLevelLoad,
|
324
328
|
);
|
325
|
-
if (
|
329
|
+
if (
|
330
|
+
fragLevelNextLoadedDelay <
|
331
|
+
Math.min(bufferStarvationDelay, duration + ttfbSeconds)
|
332
|
+
) {
|
326
333
|
break;
|
327
334
|
}
|
328
335
|
}
|
@@ -336,7 +343,6 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
336
343
|
if (fragLevelNextLoadedDelay > duration * 10) {
|
337
344
|
return;
|
338
345
|
}
|
339
|
-
hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
|
340
346
|
if (loadedFirstByte) {
|
341
347
|
// If there has been loading progress, sample bandwidth using loading time offset by minimum TTFB time
|
342
348
|
this.bwEstimator.sample(
|
@@ -348,17 +354,26 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
348
354
|
this.bwEstimator.sampleTTFB(timeLoading);
|
349
355
|
}
|
350
356
|
const nextLoadLevelBitrate = levels[nextLoadLevel].maxBitrate;
|
351
|
-
if (
|
352
|
-
this.getBwEstimate() * this.hls.config.abrBandWidthUpFactor >
|
353
|
-
nextLoadLevelBitrate
|
354
|
-
) {
|
357
|
+
if (this.getBwEstimate() * abrBandWidthUpFactor > nextLoadLevelBitrate) {
|
355
358
|
this.resetEstimator(nextLoadLevelBitrate);
|
356
359
|
}
|
360
|
+
const bestSwitchLevel = this.findBestLevel(
|
361
|
+
nextLoadLevelBitrate,
|
362
|
+
minAutoLevel,
|
363
|
+
nextLoadLevel,
|
364
|
+
0,
|
365
|
+
bufferStarvationDelay,
|
366
|
+
1,
|
367
|
+
1,
|
368
|
+
);
|
369
|
+
if (bestSwitchLevel > -1) {
|
370
|
+
nextLoadLevel = bestSwitchLevel;
|
371
|
+
}
|
357
372
|
|
358
|
-
this.clearTimer();
|
359
373
|
this.warn(`Fragment ${frag.sn}${
|
360
374
|
part ? ' part ' + part.index : ''
|
361
375
|
} of level ${frag.level} is loading too slowly;
|
376
|
+
Fragment duration: ${frag.duration.toFixed(3)}
|
362
377
|
Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s
|
363
378
|
Estimated load time for current fragment: ${fragLoadedDelay.toFixed(3)} s
|
364
379
|
Estimated load time for down switch fragment: ${fragLevelNextLoadedDelay.toFixed(
|
@@ -370,6 +385,44 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
370
385
|
} bps
|
371
386
|
New BW estimate: ${this.getBwEstimate() | 0} bps
|
372
387
|
Switching to level ${nextLoadLevel} @ ${nextLoadLevelBitrate | 0} bps`);
|
388
|
+
|
389
|
+
hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
|
390
|
+
|
391
|
+
this.clearTimer();
|
392
|
+
this.timer = self.setInterval(() => {
|
393
|
+
// Are nextLoadLevel details available or is stream-controller still in "WAITING_LEVEL" state?
|
394
|
+
this.clearTimer();
|
395
|
+
if (
|
396
|
+
this.fragCurrent === frag &&
|
397
|
+
this.hls.loadLevel === nextLoadLevel &&
|
398
|
+
nextLoadLevel > 0
|
399
|
+
) {
|
400
|
+
const bufferStarvationDelay = this.getStarvationDelay();
|
401
|
+
this
|
402
|
+
.warn(`Aborting inflight request ${nextLoadLevel > 0 ? 'and switching down' : ''}
|
403
|
+
Fragment duration: ${frag.duration.toFixed(3)} s
|
404
|
+
Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s`);
|
405
|
+
frag.abortRequests();
|
406
|
+
this.fragCurrent = this.partCurrent = null;
|
407
|
+
if (nextLoadLevel > minAutoLevel) {
|
408
|
+
let lowestSwitchLevel = this.findBestLevel(
|
409
|
+
this.hls.levels[minAutoLevel].bitrate,
|
410
|
+
minAutoLevel,
|
411
|
+
nextLoadLevel,
|
412
|
+
0,
|
413
|
+
bufferStarvationDelay,
|
414
|
+
1,
|
415
|
+
1,
|
416
|
+
);
|
417
|
+
if (lowestSwitchLevel === -1) {
|
418
|
+
lowestSwitchLevel = minAutoLevel;
|
419
|
+
}
|
420
|
+
this.hls.nextLoadLevel = this.hls.nextAutoLevel = lowestSwitchLevel;
|
421
|
+
this.resetEstimator(this.hls.levels[lowestSwitchLevel].bitrate);
|
422
|
+
}
|
423
|
+
}
|
424
|
+
}, fragLevelNextLoadedDelay * 1000);
|
425
|
+
|
373
426
|
hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, { frag, part, stats });
|
374
427
|
};
|
375
428
|
|
@@ -665,7 +718,7 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
665
718
|
return 0;
|
666
719
|
}
|
667
720
|
const level: Level | undefined = levels[selectionBaseLevel];
|
668
|
-
const live = !!
|
721
|
+
const live = !!this.hls.latestLevelDetails?.live;
|
669
722
|
const firstSelection = loadLevel === -1 || lastLoadedFragLevel === -1;
|
670
723
|
let currentCodecSet: string | undefined;
|
671
724
|
let currentVideoRange: VideoRange | undefined = 'SDR';
|
@@ -439,11 +439,12 @@ export default class LevelController extends BasePlaylistController {
|
|
439
439
|
|
440
440
|
if (
|
441
441
|
lastLevelIndex === newLevel &&
|
442
|
-
level.details &&
|
443
442
|
lastLevel &&
|
444
443
|
lastPathwayId === pathwayId
|
445
444
|
) {
|
446
|
-
|
445
|
+
if (level.details || this.requestScheduled !== -1) {
|
446
|
+
return;
|
447
|
+
}
|
447
448
|
}
|
448
449
|
|
449
450
|
this.log(
|
@@ -571,7 +572,10 @@ export default class LevelController extends BasePlaylistController {
|
|
571
572
|
data.context.type === PlaylistContextType.LEVEL &&
|
572
573
|
data.context.level === this.level
|
573
574
|
) {
|
574
|
-
this.checkRetry(data);
|
575
|
+
const retry = this.checkRetry(data);
|
576
|
+
if (!retry) {
|
577
|
+
this.requestScheduled = -1;
|
578
|
+
}
|
575
579
|
}
|
576
580
|
}
|
577
581
|
|