hls.js 1.5.12-0.canary.10340 → 1.5.12-0.canary.10341
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 +431 -288
- package/dist/hls.js.d.ts +49 -16
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +364 -178
- 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 +356 -179
- 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 +422 -288
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +1 -1
- package/src/controller/audio-stream-controller.ts +13 -5
- package/src/controller/base-stream-controller.ts +28 -26
- package/src/controller/fragment-finders.ts +12 -14
- package/src/controller/fragment-tracker.ts +14 -14
- package/src/controller/id3-track-controller.ts +38 -28
- package/src/controller/stream-controller.ts +9 -4
- package/src/controller/subtitle-stream-controller.ts +3 -3
- package/src/demux/transmuxer-interface.ts +4 -4
- package/src/hls.ts +3 -1
- package/src/loader/date-range.ts +71 -5
- package/src/loader/fragment.ts +6 -2
- package/src/loader/level-details.ts +7 -6
- package/src/loader/m3u8-parser.ts +138 -144
- package/src/types/events.ts +2 -5
- package/src/types/fragment-tracker.ts +2 -2
- package/src/utils/attr-list.ts +96 -9
- package/src/utils/level-helper.ts +68 -40
- package/src/utils/variable-substitution.ts +0 -19
package/dist/hls.light.js
CHANGED
@@ -434,14 +434,90 @@
|
|
434
434
|
return ErrorDetails;
|
435
435
|
}({});
|
436
436
|
|
437
|
+
var Logger = function Logger(label, logger) {
|
438
|
+
this.trace = void 0;
|
439
|
+
this.debug = void 0;
|
440
|
+
this.log = void 0;
|
441
|
+
this.warn = void 0;
|
442
|
+
this.info = void 0;
|
443
|
+
this.error = void 0;
|
444
|
+
var lb = "[" + label + "]:";
|
445
|
+
this.trace = noop;
|
446
|
+
this.debug = logger.debug.bind(null, lb);
|
447
|
+
this.log = logger.log.bind(null, lb);
|
448
|
+
this.warn = logger.warn.bind(null, lb);
|
449
|
+
this.info = logger.info.bind(null, lb);
|
450
|
+
this.error = logger.error.bind(null, lb);
|
451
|
+
};
|
452
|
+
var noop = function noop() {};
|
453
|
+
var fakeLogger = {
|
454
|
+
trace: noop,
|
455
|
+
debug: noop,
|
456
|
+
log: noop,
|
457
|
+
warn: noop,
|
458
|
+
info: noop,
|
459
|
+
error: noop
|
460
|
+
};
|
461
|
+
function createLogger() {
|
462
|
+
return _extends({}, fakeLogger);
|
463
|
+
}
|
464
|
+
|
465
|
+
// let lastCallTime;
|
466
|
+
// function formatMsgWithTimeInfo(type, msg) {
|
467
|
+
// const now = Date.now();
|
468
|
+
// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
|
469
|
+
// lastCallTime = now;
|
470
|
+
// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
|
471
|
+
// return msg;
|
472
|
+
// }
|
473
|
+
|
474
|
+
function consolePrintFn(type, id) {
|
475
|
+
var func = self.console[type];
|
476
|
+
return func ? func.bind(self.console, ('') + "[" + type + "] >") : noop;
|
477
|
+
}
|
478
|
+
function getLoggerFn(key, debugConfig, id) {
|
479
|
+
return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key);
|
480
|
+
}
|
481
|
+
var exportedLogger = createLogger();
|
482
|
+
function enableLogs(debugConfig, context, id) {
|
483
|
+
// check that console is available
|
484
|
+
var newLogger = createLogger();
|
485
|
+
if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
|
486
|
+
var keys = [
|
487
|
+
// Remove out from list here to hard-disable a log-level
|
488
|
+
// 'trace',
|
489
|
+
'debug', 'log', 'info', 'warn', 'error'];
|
490
|
+
keys.forEach(function (key) {
|
491
|
+
newLogger[key] = getLoggerFn(key, debugConfig);
|
492
|
+
});
|
493
|
+
// Some browsers don't allow to use bind on console object anyway
|
494
|
+
// fallback to default if needed
|
495
|
+
try {
|
496
|
+
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.12-0.canary.10341");
|
497
|
+
} catch (e) {
|
498
|
+
/* log fn threw an exception. All logger methods are no-ops. */
|
499
|
+
return createLogger();
|
500
|
+
}
|
501
|
+
// global exported logger uses the same functions as new logger without `id`
|
502
|
+
keys.forEach(function (key) {
|
503
|
+
exportedLogger[key] = getLoggerFn(key, debugConfig);
|
504
|
+
});
|
505
|
+
} else {
|
506
|
+
// Reset global exported logger
|
507
|
+
_extends(exportedLogger, newLogger);
|
508
|
+
}
|
509
|
+
return newLogger;
|
510
|
+
}
|
511
|
+
var logger = exportedLogger;
|
512
|
+
|
437
513
|
var DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/;
|
438
514
|
var ATTR_LIST_REGEX = /(.+?)=(".*?"|.*?)(?:,|$)/g;
|
439
515
|
|
440
516
|
// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js
|
441
517
|
var AttrList = /*#__PURE__*/function () {
|
442
|
-
function AttrList(attrs) {
|
518
|
+
function AttrList(attrs, parsed) {
|
443
519
|
if (typeof attrs === 'string') {
|
444
|
-
attrs = AttrList.parseAttrList(attrs);
|
520
|
+
attrs = AttrList.parseAttrList(attrs, parsed);
|
445
521
|
}
|
446
522
|
_extends(this, attrs);
|
447
523
|
}
|
@@ -483,6 +559,13 @@
|
|
483
559
|
_proto.enumeratedString = function enumeratedString(attrName) {
|
484
560
|
return this[attrName];
|
485
561
|
};
|
562
|
+
_proto.enumeratedStringList = function enumeratedStringList(attrName, dict) {
|
563
|
+
var attrValue = this[attrName];
|
564
|
+
return (attrValue ? attrValue.split(/[ ,]+/) : []).reduce(function (result, identifier) {
|
565
|
+
result[identifier.toLowerCase()] = true;
|
566
|
+
return result;
|
567
|
+
}, dict);
|
568
|
+
};
|
486
569
|
_proto.bool = function bool(attrName) {
|
487
570
|
return this[attrName] === 'YES';
|
488
571
|
};
|
@@ -496,17 +579,71 @@
|
|
496
579
|
height: parseInt(res[2], 10)
|
497
580
|
};
|
498
581
|
};
|
499
|
-
AttrList.parseAttrList = function parseAttrList(input) {
|
582
|
+
AttrList.parseAttrList = function parseAttrList(input, parsed) {
|
500
583
|
var match;
|
501
584
|
var attrs = {};
|
502
585
|
var quote = '"';
|
503
586
|
ATTR_LIST_REGEX.lastIndex = 0;
|
504
587
|
while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {
|
588
|
+
var name = match[1].trim();
|
505
589
|
var value = match[2];
|
506
|
-
|
590
|
+
var quotedString = value.indexOf(quote) === 0 && value.lastIndexOf(quote) === value.length - 1;
|
591
|
+
var hexadecimalSequence = false;
|
592
|
+
if (quotedString) {
|
507
593
|
value = value.slice(1, -1);
|
594
|
+
} else {
|
595
|
+
switch (name) {
|
596
|
+
case 'IV':
|
597
|
+
case 'SCTE35-CMD':
|
598
|
+
case 'SCTE35-IN':
|
599
|
+
case 'SCTE35-OUT':
|
600
|
+
hexadecimalSequence = true;
|
601
|
+
}
|
602
|
+
}
|
603
|
+
if (parsed && (quotedString || hexadecimalSequence)) ; else if (!hexadecimalSequence && !quotedString) {
|
604
|
+
switch (name) {
|
605
|
+
case 'CLOSED-CAPTIONS':
|
606
|
+
if (value === 'NONE') {
|
607
|
+
break;
|
608
|
+
}
|
609
|
+
// falls through
|
610
|
+
case 'ALLOWED-CPC':
|
611
|
+
case 'CLASS':
|
612
|
+
case 'ASSOC-LANGUAGE':
|
613
|
+
case 'AUDIO':
|
614
|
+
case 'BYTERANGE':
|
615
|
+
case 'CHANNELS':
|
616
|
+
case 'CHARACTERISTICS':
|
617
|
+
case 'CODECS':
|
618
|
+
case 'DATA-ID':
|
619
|
+
case 'END-DATE':
|
620
|
+
case 'GROUP-ID':
|
621
|
+
case 'ID':
|
622
|
+
case 'IMPORT':
|
623
|
+
case 'INSTREAM-ID':
|
624
|
+
case 'KEYFORMAT':
|
625
|
+
case 'KEYFORMATVERSIONS':
|
626
|
+
case 'LANGUAGE':
|
627
|
+
case 'NAME':
|
628
|
+
case 'PATHWAY-ID':
|
629
|
+
case 'QUERYPARAM':
|
630
|
+
case 'RECENTLY-REMOVED-DATERANGES':
|
631
|
+
case 'SERVER-URI':
|
632
|
+
case 'STABLE-RENDITION-ID':
|
633
|
+
case 'STABLE-VARIANT-ID':
|
634
|
+
case 'START-DATE':
|
635
|
+
case 'SUBTITLES':
|
636
|
+
case 'SUPPLEMENTAL-CODECS':
|
637
|
+
case 'URI':
|
638
|
+
case 'VALUE':
|
639
|
+
case 'VIDEO':
|
640
|
+
case 'X-ASSET-LIST':
|
641
|
+
case 'X-ASSET-URI':
|
642
|
+
// Since we are not checking tag:attribute combination, just warn rather than ignoring attribute
|
643
|
+
logger.warn(input + ": attribute " + name + " is missing quotes");
|
644
|
+
// continue;
|
645
|
+
}
|
508
646
|
}
|
509
|
-
var name = match[1].trim();
|
510
647
|
attrs[name] = value;
|
511
648
|
}
|
512
649
|
return attrs;
|
@@ -521,96 +658,30 @@
|
|
521
658
|
}]);
|
522
659
|
}();
|
523
660
|
|
524
|
-
var Logger = function Logger(label, logger) {
|
525
|
-
this.trace = void 0;
|
526
|
-
this.debug = void 0;
|
527
|
-
this.log = void 0;
|
528
|
-
this.warn = void 0;
|
529
|
-
this.info = void 0;
|
530
|
-
this.error = void 0;
|
531
|
-
var lb = "[" + label + "]:";
|
532
|
-
this.trace = noop;
|
533
|
-
this.debug = logger.debug.bind(null, lb);
|
534
|
-
this.log = logger.log.bind(null, lb);
|
535
|
-
this.warn = logger.warn.bind(null, lb);
|
536
|
-
this.info = logger.info.bind(null, lb);
|
537
|
-
this.error = logger.error.bind(null, lb);
|
538
|
-
};
|
539
|
-
var noop = function noop() {};
|
540
|
-
var fakeLogger = {
|
541
|
-
trace: noop,
|
542
|
-
debug: noop,
|
543
|
-
log: noop,
|
544
|
-
warn: noop,
|
545
|
-
info: noop,
|
546
|
-
error: noop
|
547
|
-
};
|
548
|
-
function createLogger() {
|
549
|
-
return _extends({}, fakeLogger);
|
550
|
-
}
|
551
|
-
|
552
|
-
// let lastCallTime;
|
553
|
-
// function formatMsgWithTimeInfo(type, msg) {
|
554
|
-
// const now = Date.now();
|
555
|
-
// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
|
556
|
-
// lastCallTime = now;
|
557
|
-
// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
|
558
|
-
// return msg;
|
559
|
-
// }
|
560
|
-
|
561
|
-
function consolePrintFn(type, id) {
|
562
|
-
var func = self.console[type];
|
563
|
-
return func ? func.bind(self.console, ('') + "[" + type + "] >") : noop;
|
564
|
-
}
|
565
|
-
function getLoggerFn(key, debugConfig, id) {
|
566
|
-
return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key);
|
567
|
-
}
|
568
|
-
var exportedLogger = createLogger();
|
569
|
-
function enableLogs(debugConfig, context, id) {
|
570
|
-
// check that console is available
|
571
|
-
var newLogger = createLogger();
|
572
|
-
if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
|
573
|
-
var keys = [
|
574
|
-
// Remove out from list here to hard-disable a log-level
|
575
|
-
// 'trace',
|
576
|
-
'debug', 'log', 'info', 'warn', 'error'];
|
577
|
-
keys.forEach(function (key) {
|
578
|
-
newLogger[key] = getLoggerFn(key, debugConfig);
|
579
|
-
});
|
580
|
-
// Some browsers don't allow to use bind on console object anyway
|
581
|
-
// fallback to default if needed
|
582
|
-
try {
|
583
|
-
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.12-0.canary.10340");
|
584
|
-
} catch (e) {
|
585
|
-
/* log fn threw an exception. All logger methods are no-ops. */
|
586
|
-
return createLogger();
|
587
|
-
}
|
588
|
-
// global exported logger uses the same functions as new logger without `id`
|
589
|
-
keys.forEach(function (key) {
|
590
|
-
exportedLogger[key] = getLoggerFn(key, debugConfig);
|
591
|
-
});
|
592
|
-
} else {
|
593
|
-
// Reset global exported logger
|
594
|
-
_extends(exportedLogger, newLogger);
|
595
|
-
}
|
596
|
-
return newLogger;
|
597
|
-
}
|
598
|
-
var logger = exportedLogger;
|
599
|
-
|
600
661
|
// Avoid exporting const enum so that these values can be inlined
|
601
662
|
|
663
|
+
var CLASS_INTERSTITIAL = 'com.apple.hls.interstitial';
|
602
664
|
function isDateRangeCueAttribute(attrName) {
|
603
|
-
return attrName !== "ID" && attrName !== "CLASS" && attrName !== "START-DATE" && attrName !== "DURATION" && attrName !== "END-DATE" && attrName !== "END-ON-NEXT";
|
665
|
+
return attrName !== "ID" && attrName !== "CLASS" && attrName !== "CUE" && attrName !== "START-DATE" && attrName !== "DURATION" && attrName !== "END-DATE" && attrName !== "END-ON-NEXT";
|
604
666
|
}
|
605
667
|
function isSCTE35Attribute(attrName) {
|
606
|
-
return attrName === "SCTE35-OUT" || attrName === "SCTE35-IN";
|
668
|
+
return attrName === "SCTE35-OUT" || attrName === "SCTE35-IN" || attrName === "SCTE35-CMD";
|
607
669
|
}
|
608
670
|
var DateRange = /*#__PURE__*/function () {
|
609
|
-
function DateRange(dateRangeAttr, dateRangeWithSameId) {
|
671
|
+
function DateRange(dateRangeAttr, dateRangeWithSameId, tagCount) {
|
672
|
+
var _dateRangeWithSameId$;
|
673
|
+
if (tagCount === void 0) {
|
674
|
+
tagCount = 0;
|
675
|
+
}
|
610
676
|
this.attr = void 0;
|
677
|
+
this.tagAnchor = void 0;
|
678
|
+
this.tagOrder = void 0;
|
611
679
|
this._startDate = void 0;
|
612
680
|
this._endDate = void 0;
|
681
|
+
this._cue = void 0;
|
613
682
|
this._badValueForSameId = void 0;
|
683
|
+
this.tagAnchor = (dateRangeWithSameId == null ? void 0 : dateRangeWithSameId.tagAnchor) || null;
|
684
|
+
this.tagOrder = (_dateRangeWithSameId$ = dateRangeWithSameId == null ? void 0 : dateRangeWithSameId.tagOrder) != null ? _dateRangeWithSameId$ : tagCount;
|
614
685
|
if (dateRangeWithSameId) {
|
615
686
|
var previousAttr = dateRangeWithSameId.attr;
|
616
687
|
for (var key in previousAttr) {
|
@@ -624,9 +695,9 @@
|
|
624
695
|
dateRangeAttr = _extends(new AttrList({}), previousAttr, dateRangeAttr);
|
625
696
|
}
|
626
697
|
this.attr = dateRangeAttr;
|
627
|
-
this._startDate = new Date(dateRangeAttr["START-DATE"]);
|
698
|
+
this._startDate = dateRangeWithSameId ? dateRangeWithSameId.startDate : new Date(dateRangeAttr["START-DATE"]);
|
628
699
|
if ("END-DATE" in this.attr) {
|
629
|
-
var endDate = new Date(this.attr["END-DATE"]);
|
700
|
+
var endDate = (dateRangeWithSameId == null ? void 0 : dateRangeWithSameId.endDate) || new Date(this.attr["END-DATE"]);
|
630
701
|
if (isFiniteNumber(endDate.getTime())) {
|
631
702
|
this._endDate = endDate;
|
632
703
|
}
|
@@ -642,6 +713,30 @@
|
|
642
713
|
get: function get() {
|
643
714
|
return this.attr.CLASS;
|
644
715
|
}
|
716
|
+
}, {
|
717
|
+
key: "cue",
|
718
|
+
get: function get() {
|
719
|
+
var _cue = this._cue;
|
720
|
+
if (_cue === undefined) {
|
721
|
+
return this._cue = this.attr.enumeratedStringList(this.attr.CUE ? 'CUE' : 'X-CUE', {
|
722
|
+
pre: false,
|
723
|
+
post: false,
|
724
|
+
once: false
|
725
|
+
});
|
726
|
+
}
|
727
|
+
return _cue;
|
728
|
+
}
|
729
|
+
}, {
|
730
|
+
key: "startTime",
|
731
|
+
get: function get() {
|
732
|
+
var tagAnchor = this.tagAnchor;
|
733
|
+
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
734
|
+
if (tagAnchor === null || tagAnchor.programDateTime === null) {
|
735
|
+
logger.warn("Expected tagAnchor Fragment with PDT set for DateRange \"" + this.id + "\": " + tagAnchor);
|
736
|
+
return NaN;
|
737
|
+
}
|
738
|
+
return tagAnchor.start + (this.startDate.getTime() - tagAnchor.programDateTime) / 1000;
|
739
|
+
}
|
645
740
|
}, {
|
646
741
|
key: "startDate",
|
647
742
|
get: function get() {
|
@@ -685,10 +780,15 @@
|
|
685
780
|
get: function get() {
|
686
781
|
return this.attr.bool("END-ON-NEXT");
|
687
782
|
}
|
783
|
+
}, {
|
784
|
+
key: "isInterstitial",
|
785
|
+
get: function get() {
|
786
|
+
return this.class === CLASS_INTERSTITIAL;
|
787
|
+
}
|
688
788
|
}, {
|
689
789
|
key: "isValid",
|
690
790
|
get: function get() {
|
691
|
-
return !!this.id && !this._badValueForSameId && isFiniteNumber(this.startDate.getTime()) && (this.duration === null || this.duration >= 0) && (!this.endOnNext || !!this.class);
|
791
|
+
return !!this.id && !this._badValueForSameId && isFiniteNumber(this.startDate.getTime()) && (this.duration === null || this.duration >= 0) && (!this.endOnNext || !!this.class) && (!this.attr.CUE || !this.cue.pre && !this.cue.post || this.cue.pre !== this.cue.post) && (!this.isInterstitial || 'X-ASSET-URI' in this.attr || 'X-ASSET-LIST' in this.attr);
|
692
792
|
}
|
693
793
|
}]);
|
694
794
|
}();
|
@@ -780,7 +880,6 @@
|
|
780
880
|
}
|
781
881
|
}]);
|
782
882
|
}();
|
783
|
-
|
784
883
|
/**
|
785
884
|
* Object representing parsed data from an HLS Segment. Found in {@link hls.js#LevelDetails.fragments}.
|
786
885
|
*/
|
@@ -1011,6 +1110,7 @@
|
|
1011
1110
|
this.fragmentHint = void 0;
|
1012
1111
|
this.partList = null;
|
1013
1112
|
this.dateRanges = void 0;
|
1113
|
+
this.dateRangeTagCount = 0;
|
1014
1114
|
this.live = true;
|
1015
1115
|
this.ageHeader = 0;
|
1016
1116
|
this.advancedDateTime = void 0;
|
@@ -2659,7 +2759,7 @@
|
|
2659
2759
|
if (result[1]) {
|
2660
2760
|
var _level$unknownCodecs;
|
2661
2761
|
// '#EXT-X-STREAM-INF' is found, parse level tag in group 1
|
2662
|
-
var attrs = new AttrList(result[1]);
|
2762
|
+
var attrs = new AttrList(result[1], parsed);
|
2663
2763
|
var uri = result[2];
|
2664
2764
|
var level = {
|
2665
2765
|
attrs: attrs,
|
@@ -2684,7 +2784,7 @@
|
|
2684
2784
|
case 'SESSION-DATA':
|
2685
2785
|
{
|
2686
2786
|
// #EXT-X-SESSION-DATA
|
2687
|
-
var sessionAttrs = new AttrList(attributes);
|
2787
|
+
var sessionAttrs = new AttrList(attributes, parsed);
|
2688
2788
|
var dataId = sessionAttrs['DATA-ID'];
|
2689
2789
|
if (dataId) {
|
2690
2790
|
if (parsed.sessionData === null) {
|
@@ -2697,7 +2797,7 @@
|
|
2697
2797
|
case 'SESSION-KEY':
|
2698
2798
|
{
|
2699
2799
|
// #EXT-X-SESSION-KEY
|
2700
|
-
var sessionKey = parseKey(attributes, baseurl);
|
2800
|
+
var sessionKey = parseKey(attributes, baseurl, parsed);
|
2701
2801
|
if (sessionKey.encrypted && sessionKey.isSupported()) {
|
2702
2802
|
if (parsed.sessionKeys === null) {
|
2703
2803
|
parsed.sessionKeys = [];
|
@@ -2715,7 +2815,7 @@
|
|
2715
2815
|
case 'CONTENT-STEERING':
|
2716
2816
|
{
|
2717
2817
|
// #EXT-X-CONTENT-STEERING
|
2718
|
-
var contentSteeringAttributes = new AttrList(attributes);
|
2818
|
+
var contentSteeringAttributes = new AttrList(attributes, parsed);
|
2719
2819
|
parsed.contentSteering = {
|
2720
2820
|
uri: M3U8Parser.resolve(contentSteeringAttributes['SERVER-URI'], baseurl),
|
2721
2821
|
pathwayId: contentSteeringAttributes['PATHWAY-ID'] || '.'
|
@@ -2761,7 +2861,7 @@
|
|
2761
2861
|
var id = 0;
|
2762
2862
|
MASTER_PLAYLIST_MEDIA_REGEX.lastIndex = 0;
|
2763
2863
|
while ((result = MASTER_PLAYLIST_MEDIA_REGEX.exec(string)) !== null) {
|
2764
|
-
var attrs = new AttrList(result[1]);
|
2864
|
+
var attrs = new AttrList(result[1], parsed);
|
2765
2865
|
var type = attrs.TYPE;
|
2766
2866
|
if (type) {
|
2767
2867
|
var groups = groupsByType[type];
|
@@ -2813,6 +2913,7 @@
|
|
2813
2913
|
M3U8Parser.parseLevelPlaylist = function parseLevelPlaylist(string, baseurl, id, type, levelUrlId, multivariantVariableList) {
|
2814
2914
|
var level = new LevelDetails(baseurl);
|
2815
2915
|
var fragments = level.fragments;
|
2916
|
+
var programDateTimes = [];
|
2816
2917
|
// The most recent init segment seen (applies to all subsequent segments)
|
2817
2918
|
var currentInitSegment = null;
|
2818
2919
|
var currentSN = 0;
|
@@ -2871,7 +2972,7 @@
|
|
2871
2972
|
// avoid sliced strings https://github.com/video-dev/hls.js/issues/939
|
2872
2973
|
var uri = (' ' + result[3]).slice(1);
|
2873
2974
|
frag.relurl = uri;
|
2874
|
-
assignProgramDateTime(frag, prevFrag);
|
2975
|
+
assignProgramDateTime(frag, prevFrag, programDateTimes);
|
2875
2976
|
prevFrag = frag;
|
2876
2977
|
totalduration += frag.duration;
|
2877
2978
|
currentSN++;
|
@@ -2919,19 +3020,22 @@
|
|
2919
3020
|
break;
|
2920
3021
|
case 'SKIP':
|
2921
3022
|
{
|
2922
|
-
|
3023
|
+
if (level.skippedSegments) {
|
3024
|
+
level.playlistParsingError = new Error("#EXT-X-SKIP MUST NOT appear more than once in a Playlist");
|
3025
|
+
}
|
3026
|
+
var skipAttrs = new AttrList(value1, level);
|
2923
3027
|
var skippedSegments = skipAttrs.decimalInteger('SKIPPED-SEGMENTS');
|
2924
3028
|
if (isFiniteNumber(skippedSegments)) {
|
2925
|
-
level.skippedSegments
|
3029
|
+
level.skippedSegments += skippedSegments;
|
2926
3030
|
// This will result in fragments[] containing undefined values, which we will fill in with `mergeDetails`
|
2927
3031
|
for (var _i = skippedSegments; _i--;) {
|
2928
|
-
fragments.
|
3032
|
+
fragments.push(null);
|
2929
3033
|
}
|
2930
3034
|
currentSN += skippedSegments;
|
2931
3035
|
}
|
2932
3036
|
var recentlyRemovedDateranges = skipAttrs.enumeratedString('RECENTLY-REMOVED-DATERANGES');
|
2933
3037
|
if (recentlyRemovedDateranges) {
|
2934
|
-
level.recentlyRemovedDateranges = recentlyRemovedDateranges.split('\t');
|
3038
|
+
level.recentlyRemovedDateranges = (level.recentlyRemovedDateranges || []).concat(recentlyRemovedDateranges.split('\t'));
|
2935
3039
|
}
|
2936
3040
|
break;
|
2937
3041
|
}
|
@@ -2965,8 +3069,9 @@
|
|
2965
3069
|
break;
|
2966
3070
|
case 'DATERANGE':
|
2967
3071
|
{
|
2968
|
-
var dateRangeAttr = new AttrList(value1);
|
2969
|
-
var dateRange = new DateRange(dateRangeAttr, level.dateRanges[dateRangeAttr.ID]);
|
3072
|
+
var dateRangeAttr = new AttrList(value1, level);
|
3073
|
+
var dateRange = new DateRange(dateRangeAttr, level.dateRanges[dateRangeAttr.ID], level.dateRangeTagCount);
|
3074
|
+
level.dateRangeTagCount++;
|
2970
3075
|
if (dateRange.isValid || level.skippedSegments) {
|
2971
3076
|
level.dateRanges[dateRange.id] = dateRange;
|
2972
3077
|
} else {
|
@@ -2985,7 +3090,7 @@
|
|
2985
3090
|
break;
|
2986
3091
|
case 'KEY':
|
2987
3092
|
{
|
2988
|
-
var levelKey = parseKey(value1, baseurl);
|
3093
|
+
var levelKey = parseKey(value1, baseurl, level);
|
2989
3094
|
if (levelKey.isSupported()) {
|
2990
3095
|
if (levelKey.method === 'NONE') {
|
2991
3096
|
levelkeys = undefined;
|
@@ -3008,7 +3113,7 @@
|
|
3008
3113
|
break;
|
3009
3114
|
case 'MAP':
|
3010
3115
|
{
|
3011
|
-
var mapAttrs = new AttrList(value1);
|
3116
|
+
var mapAttrs = new AttrList(value1, level);
|
3012
3117
|
if (frag.duration) {
|
3013
3118
|
// Initial segment tag is after segment duration tag.
|
3014
3119
|
// #EXTINF: 6.0
|
@@ -3034,6 +3139,7 @@
|
|
3034
3139
|
currentInitSegment = frag;
|
3035
3140
|
createNextFrag = true;
|
3036
3141
|
}
|
3142
|
+
currentInitSegment.cc = discontinuityCounter;
|
3037
3143
|
break;
|
3038
3144
|
}
|
3039
3145
|
case 'SERVER-CONTROL':
|
@@ -3060,7 +3166,7 @@
|
|
3060
3166
|
}
|
3061
3167
|
var previousFragmentPart = currentPart > 0 ? partList[partList.length - 1] : undefined;
|
3062
3168
|
var index = currentPart++;
|
3063
|
-
var partAttrs = new AttrList(value1);
|
3169
|
+
var partAttrs = new AttrList(value1, level);
|
3064
3170
|
var part = new Part(partAttrs, frag, baseurl, index, previousFragmentPart);
|
3065
3171
|
partList.push(part);
|
3066
3172
|
frag.duration += part.duration;
|
@@ -3068,13 +3174,13 @@
|
|
3068
3174
|
}
|
3069
3175
|
case 'PRELOAD-HINT':
|
3070
3176
|
{
|
3071
|
-
var preloadHintAttrs = new AttrList(value1);
|
3177
|
+
var preloadHintAttrs = new AttrList(value1, level);
|
3072
3178
|
level.preloadHint = preloadHintAttrs;
|
3073
3179
|
break;
|
3074
3180
|
}
|
3075
3181
|
case 'RENDITION-REPORT':
|
3076
3182
|
{
|
3077
|
-
var renditionReportAttrs = new AttrList(value1);
|
3183
|
+
var renditionReportAttrs = new AttrList(value1, level);
|
3078
3184
|
level.renditionReports = level.renditionReports || [];
|
3079
3185
|
level.renditionReports.push(renditionReportAttrs);
|
3080
3186
|
break;
|
@@ -3092,7 +3198,7 @@
|
|
3092
3198
|
level.fragmentHint = prevFrag;
|
3093
3199
|
}
|
3094
3200
|
} else if (level.partList) {
|
3095
|
-
assignProgramDateTime(frag, prevFrag);
|
3201
|
+
assignProgramDateTime(frag, prevFrag, programDateTimes);
|
3096
3202
|
frag.cc = discontinuityCounter;
|
3097
3203
|
level.fragmentHint = frag;
|
3098
3204
|
if (levelkeys) {
|
@@ -3113,6 +3219,21 @@
|
|
3113
3219
|
if (firstFragment) {
|
3114
3220
|
level.startCC = firstFragment.cc;
|
3115
3221
|
}
|
3222
|
+
/**
|
3223
|
+
* Backfill any missing PDT values
|
3224
|
+
* "If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after
|
3225
|
+
* one or more Media Segment URIs, the client SHOULD extrapolate
|
3226
|
+
* backward from that tag (using EXTINF durations and/or media
|
3227
|
+
* timestamps) to associate dates with those segments."
|
3228
|
+
* We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs
|
3229
|
+
* computed.
|
3230
|
+
*/
|
3231
|
+
if (firstPdtIndex > 0) {
|
3232
|
+
backfillProgramDateTimes(fragments, firstPdtIndex);
|
3233
|
+
if (firstFragment) {
|
3234
|
+
programDateTimes.unshift(firstFragment);
|
3235
|
+
}
|
3236
|
+
}
|
3116
3237
|
} else {
|
3117
3238
|
level.endSN = 0;
|
3118
3239
|
level.startCC = 0;
|
@@ -3121,28 +3242,63 @@
|
|
3121
3242
|
totalduration += level.fragmentHint.duration;
|
3122
3243
|
}
|
3123
3244
|
level.totalduration = totalduration;
|
3124
|
-
level.
|
3125
|
-
|
3126
|
-
/**
|
3127
|
-
* Backfill any missing PDT values
|
3128
|
-
* "If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after
|
3129
|
-
* one or more Media Segment URIs, the client SHOULD extrapolate
|
3130
|
-
* backward from that tag (using EXTINF durations and/or media
|
3131
|
-
* timestamps) to associate dates with those segments."
|
3132
|
-
* We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs
|
3133
|
-
* computed.
|
3134
|
-
*/
|
3135
|
-
if (firstPdtIndex > 0) {
|
3136
|
-
backfillProgramDateTimes(fragments, firstPdtIndex);
|
3245
|
+
if (programDateTimes.length && level.dateRangeTagCount && firstFragment) {
|
3246
|
+
mapDateRanges(programDateTimes, level);
|
3137
3247
|
}
|
3248
|
+
level.endCC = discontinuityCounter;
|
3138
3249
|
return level;
|
3139
3250
|
};
|
3140
3251
|
return M3U8Parser;
|
3141
3252
|
}();
|
3253
|
+
function mapDateRanges(programDateTimes, details) {
|
3254
|
+
// Make sure DateRanges are mapped to a ProgramDateTime tag that applies a date to a segment that overlaps with its start date
|
3255
|
+
var programDateTimeCount = programDateTimes.length;
|
3256
|
+
var lastProgramDateTime = programDateTimes[programDateTimeCount - 1];
|
3257
|
+
var playlistEnd = details.live ? Infinity : details.totalduration;
|
3258
|
+
var dateRangeIds = Object.keys(details.dateRanges);
|
3259
|
+
for (var i = dateRangeIds.length; i--;) {
|
3260
|
+
var dateRange = details.dateRanges[dateRangeIds[i]];
|
3261
|
+
var startDateTime = dateRange.startDate.getTime();
|
3262
|
+
dateRange.tagAnchor = lastProgramDateTime;
|
3263
|
+
for (var j = programDateTimeCount; j--;) {
|
3264
|
+
var fragIndex = findFragmentWithStartDate(details, startDateTime, programDateTimes, j, playlistEnd);
|
3265
|
+
if (fragIndex !== -1) {
|
3266
|
+
dateRange.tagAnchor = details.fragments[fragIndex];
|
3267
|
+
break;
|
3268
|
+
}
|
3269
|
+
}
|
3270
|
+
}
|
3271
|
+
}
|
3272
|
+
function findFragmentWithStartDate(details, startDateTime, programDateTimes, index, endTime) {
|
3273
|
+
var pdtFragment = programDateTimes[index];
|
3274
|
+
if (pdtFragment) {
|
3275
|
+
var _programDateTimes;
|
3276
|
+
// find matching range between PDT tags
|
3277
|
+
var durationBetweenPdt = (((_programDateTimes = programDateTimes[index + 1]) == null ? void 0 : _programDateTimes.start) || endTime) - pdtFragment.start;
|
3278
|
+
var pdtStart = pdtFragment.programDateTime;
|
3279
|
+
if ((startDateTime >= pdtStart || index === 0) && startDateTime <= pdtStart + durationBetweenPdt * 1000) {
|
3280
|
+
// map to fragment with date-time range
|
3281
|
+
var startIndex = programDateTimes[index].sn - details.startSN;
|
3282
|
+
var fragments = details.fragments;
|
3283
|
+
if (fragments.length > programDateTimes.length) {
|
3284
|
+
var endSegment = programDateTimes[index + 1] || fragments[fragments.length - 1];
|
3285
|
+
var endIndex = endSegment.sn - details.startSN;
|
3286
|
+
for (var i = endIndex; i > startIndex; i--) {
|
3287
|
+
var fragStartDateTime = fragments[i].programDateTime;
|
3288
|
+
if (startDateTime >= fragStartDateTime && startDateTime < fragStartDateTime + fragments[i].duration * 1000) {
|
3289
|
+
return i;
|
3290
|
+
}
|
3291
|
+
}
|
3292
|
+
}
|
3293
|
+
return startIndex;
|
3294
|
+
}
|
3295
|
+
}
|
3296
|
+
return -1;
|
3297
|
+
}
|
3142
3298
|
function parseKey(keyTagAttributes, baseurl, parsed) {
|
3143
3299
|
var _keyAttrs$METHOD, _keyAttrs$KEYFORMAT;
|
3144
3300
|
// https://tools.ietf.org/html/rfc8216#section-4.3.2.4
|
3145
|
-
var keyAttrs = new AttrList(keyTagAttributes);
|
3301
|
+
var keyAttrs = new AttrList(keyTagAttributes, parsed);
|
3146
3302
|
var decryptmethod = (_keyAttrs$METHOD = keyAttrs.METHOD) != null ? _keyAttrs$METHOD : '';
|
3147
3303
|
var decrypturi = keyAttrs.URI;
|
3148
3304
|
var decryptiv = keyAttrs.hexadecimalInteger('IV');
|
@@ -3203,16 +3359,18 @@
|
|
3203
3359
|
fragPrev = frag;
|
3204
3360
|
}
|
3205
3361
|
}
|
3206
|
-
function assignProgramDateTime(frag, prevFrag) {
|
3362
|
+
function assignProgramDateTime(frag, prevFrag, programDateTimes) {
|
3207
3363
|
if (frag.rawProgramDateTime) {
|
3208
3364
|
frag.programDateTime = Date.parse(frag.rawProgramDateTime);
|
3365
|
+
if (!isFiniteNumber(frag.programDateTime)) {
|
3366
|
+
frag.programDateTime = null;
|
3367
|
+
frag.rawProgramDateTime = null;
|
3368
|
+
return;
|
3369
|
+
}
|
3370
|
+
programDateTimes.push(frag);
|
3209
3371
|
} else if (prevFrag != null && prevFrag.programDateTime) {
|
3210
3372
|
frag.programDateTime = prevFrag.endProgramDateTime;
|
3211
3373
|
}
|
3212
|
-
if (!isFiniteNumber(frag.programDateTime)) {
|
3213
|
-
frag.programDateTime = null;
|
3214
|
-
frag.rawProgramDateTime = null;
|
3215
|
-
}
|
3216
3374
|
}
|
3217
3375
|
function setInitSegment(frag, mapAttrs, id, levelkeys) {
|
3218
3376
|
frag.relurl = mapAttrs.URI;
|
@@ -4292,9 +4450,6 @@
|
|
4292
4450
|
}
|
4293
4451
|
return Number.POSITIVE_INFINITY;
|
4294
4452
|
}();
|
4295
|
-
function dateRangeDateToTimelineSeconds(date, offset) {
|
4296
|
-
return date.getTime() / 1000 - offset;
|
4297
|
-
}
|
4298
4453
|
function hexToArrayBuffer(str) {
|
4299
4454
|
return Uint8Array.from(str.replace(/^0x/, '').replace(/([\da-fA-F]{2}) ?/g, '0x$1 ').replace(/ +$/, '').split(' ')).buffer;
|
4300
4455
|
}
|
@@ -4324,6 +4479,7 @@
|
|
4324
4479
|
hls.on(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);
|
4325
4480
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
4326
4481
|
hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);
|
4482
|
+
hls.on(Events.LEVEL_PTS_UPDATED, this.onLevelPtsUpdated, this);
|
4327
4483
|
};
|
4328
4484
|
_proto._unregisterListeners = function _unregisterListeners() {
|
4329
4485
|
var hls = this.hls;
|
@@ -4333,6 +4489,7 @@
|
|
4333
4489
|
hls.off(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);
|
4334
4490
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
4335
4491
|
hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);
|
4492
|
+
hls.off(Events.LEVEL_PTS_UPDATED, this.onLevelPtsUpdated, this);
|
4336
4493
|
}
|
4337
4494
|
|
4338
4495
|
// Add ID3 metatadata text track.
|
@@ -4465,8 +4622,16 @@
|
|
4465
4622
|
}
|
4466
4623
|
};
|
4467
4624
|
_proto.onLevelUpdated = function onLevelUpdated(event, _ref2) {
|
4468
|
-
var _this = this;
|
4469
4625
|
var details = _ref2.details;
|
4626
|
+
this.updateDateRangeCues(details, true);
|
4627
|
+
};
|
4628
|
+
_proto.onLevelPtsUpdated = function onLevelPtsUpdated(event, data) {
|
4629
|
+
if (Math.abs(data.drift) > 0.01) {
|
4630
|
+
this.updateDateRangeCues(data.details);
|
4631
|
+
}
|
4632
|
+
};
|
4633
|
+
_proto.updateDateRangeCues = function updateDateRangeCues(details, removeOldCues) {
|
4634
|
+
var _this = this;
|
4470
4635
|
if (!this.media || !details.hasProgramDateTime || !this.hls.config.enableDateRangeMetadataCues) {
|
4471
4636
|
return;
|
4472
4637
|
}
|
@@ -4475,7 +4640,7 @@
|
|
4475
4640
|
var dateRanges = details.dateRanges;
|
4476
4641
|
var ids = Object.keys(dateRanges);
|
4477
4642
|
// Remove cues from track not found in details.dateRanges
|
4478
|
-
if (id3Track) {
|
4643
|
+
if (id3Track && removeOldCues) {
|
4479
4644
|
var idsToRemove = Object.keys(dateRangeCuesAppended).filter(function (id) {
|
4480
4645
|
return !ids.includes(id);
|
4481
4646
|
});
|
@@ -4498,21 +4663,21 @@
|
|
4498
4663
|
if (!this.id3Track) {
|
4499
4664
|
this.id3Track = this.createTrack(this.media);
|
4500
4665
|
}
|
4501
|
-
var dateTimeOffset = lastFragment.programDateTime / 1000 - lastFragment.start;
|
4502
4666
|
var Cue = getCueClass();
|
4503
4667
|
var _loop2 = function _loop2() {
|
4504
4668
|
var id = ids[_i];
|
4505
4669
|
var dateRange = dateRanges[id];
|
4506
|
-
var startTime =
|
4670
|
+
var startTime = dateRange.startTime;
|
4507
4671
|
|
4508
4672
|
// Process DateRanges to determine end-time (known DURATION, END-DATE, or END-ON-NEXT)
|
4509
4673
|
var appendedDateRangeCues = dateRangeCuesAppended[id];
|
4510
4674
|
var cues = (appendedDateRangeCues == null ? void 0 : appendedDateRangeCues.cues) || {};
|
4511
4675
|
var durationKnown = (appendedDateRangeCues == null ? void 0 : appendedDateRangeCues.durationKnown) || false;
|
4512
4676
|
var endTime = MAX_CUE_ENDTIME;
|
4513
|
-
var
|
4514
|
-
|
4515
|
-
|
4677
|
+
var duration = dateRange.duration,
|
4678
|
+
endDate = dateRange.endDate;
|
4679
|
+
if (endDate && duration !== null) {
|
4680
|
+
endTime = startTime + duration;
|
4516
4681
|
durationKnown = true;
|
4517
4682
|
} else if (dateRange.endOnNext && !durationKnown) {
|
4518
4683
|
var nextDateRangeWithSameClass = ids.reduce(function (candidateDateRange, id) {
|
@@ -4525,7 +4690,7 @@
|
|
4525
4690
|
return candidateDateRange;
|
4526
4691
|
}, null);
|
4527
4692
|
if (nextDateRangeWithSameClass) {
|
4528
|
-
endTime =
|
4693
|
+
endTime = nextDateRangeWithSameClass.startTime;
|
4529
4694
|
durationKnown = true;
|
4530
4695
|
}
|
4531
4696
|
}
|
@@ -4542,6 +4707,9 @@
|
|
4542
4707
|
if (cue) {
|
4543
4708
|
if (durationKnown && !appendedDateRangeCues.durationKnown) {
|
4544
4709
|
cue.endTime = endTime;
|
4710
|
+
} else if (Math.abs(cue.startTime - startTime) > 0.01) {
|
4711
|
+
cue.startTime = startTime;
|
4712
|
+
cue.endTime = endTime;
|
4545
4713
|
}
|
4546
4714
|
} else if (Cue) {
|
4547
4715
|
var data = dateRange.attr[key];
|
@@ -5072,7 +5240,7 @@
|
|
5072
5240
|
frag.endPTS = endPTS;
|
5073
5241
|
frag.minEndPTS = minEndPTS;
|
5074
5242
|
frag.endDTS = endDTS;
|
5075
|
-
var sn = frag.sn;
|
5243
|
+
var sn = frag.sn;
|
5076
5244
|
// exit if sn out of range
|
5077
5245
|
if (!details || sn < details.startSN || sn > details.endSN) {
|
5078
5246
|
return 0;
|
@@ -5150,8 +5318,8 @@
|
|
5150
5318
|
currentInitSegment = oldFrag.initSegment;
|
5151
5319
|
}
|
5152
5320
|
});
|
5321
|
+
var fragmentsToCheck = newDetails.fragmentHint ? newDetails.fragments.concat(newDetails.fragmentHint) : newDetails.fragments;
|
5153
5322
|
if (currentInitSegment) {
|
5154
|
-
var fragmentsToCheck = newDetails.fragmentHint ? newDetails.fragments.concat(newDetails.fragmentHint) : newDetails.fragments;
|
5155
5323
|
fragmentsToCheck.forEach(function (frag) {
|
5156
5324
|
var _currentInitSegment;
|
5157
5325
|
if (frag && (!frag.initSegment || frag.initSegment.relurl === ((_currentInitSegment = currentInitSegment) == null ? void 0 : _currentInitSegment.relurl))) {
|
@@ -5170,15 +5338,28 @@
|
|
5170
5338
|
}
|
5171
5339
|
newDetails.startSN = newDetails.fragments[0].sn;
|
5172
5340
|
newDetails.startCC = newDetails.fragments[0].cc;
|
5173
|
-
} else
|
5174
|
-
|
5341
|
+
} else {
|
5342
|
+
if (newDetails.canSkipDateRanges) {
|
5343
|
+
newDetails.dateRanges = mergeDateRanges(oldDetails.dateRanges, newDetails);
|
5344
|
+
}
|
5345
|
+
var programDateTimes = oldDetails.fragments.filter(function (frag) {
|
5346
|
+
return frag.rawProgramDateTime;
|
5347
|
+
});
|
5348
|
+
if (oldDetails.hasProgramDateTime && !newDetails.hasProgramDateTime) {
|
5349
|
+
for (var _i2 = 1; _i2 < fragmentsToCheck.length; _i2++) {
|
5350
|
+
if (fragmentsToCheck[_i2].programDateTime === null) {
|
5351
|
+
assignProgramDateTime(fragmentsToCheck[_i2], fragmentsToCheck[_i2 - 1], programDateTimes);
|
5352
|
+
}
|
5353
|
+
}
|
5354
|
+
}
|
5355
|
+
mapDateRanges(programDateTimes, newDetails);
|
5175
5356
|
}
|
5176
5357
|
}
|
5177
5358
|
var newFragments = newDetails.fragments;
|
5178
5359
|
if (ccOffset) {
|
5179
5360
|
logger.warn('discontinuity sliding from playlist, take drift into account');
|
5180
|
-
for (var
|
5181
|
-
newFragments[
|
5361
|
+
for (var _i3 = 0; _i3 < newFragments.length; _i3++) {
|
5362
|
+
newFragments[_i3].cc += ccOffset;
|
5182
5363
|
}
|
5183
5364
|
}
|
5184
5365
|
if (newDetails.skippedSegments) {
|
@@ -5220,21 +5401,31 @@
|
|
5220
5401
|
newDetails.advancedDateTime = oldDetails.advancedDateTime;
|
5221
5402
|
}
|
5222
5403
|
}
|
5223
|
-
function mergeDateRanges(oldDateRanges,
|
5404
|
+
function mergeDateRanges(oldDateRanges, newDetails) {
|
5405
|
+
var deltaDateRanges = newDetails.dateRanges,
|
5406
|
+
recentlyRemovedDateranges = newDetails.recentlyRemovedDateranges;
|
5224
5407
|
var dateRanges = _extends({}, oldDateRanges);
|
5225
5408
|
if (recentlyRemovedDateranges) {
|
5226
5409
|
recentlyRemovedDateranges.forEach(function (id) {
|
5227
5410
|
delete dateRanges[id];
|
5228
5411
|
});
|
5229
5412
|
}
|
5230
|
-
Object.keys(
|
5231
|
-
|
5232
|
-
|
5233
|
-
|
5234
|
-
|
5235
|
-
|
5236
|
-
|
5237
|
-
|
5413
|
+
var mergeIds = Object.keys(dateRanges);
|
5414
|
+
var mergeCount = mergeIds.length;
|
5415
|
+
if (mergeCount) {
|
5416
|
+
Object.keys(deltaDateRanges).forEach(function (id) {
|
5417
|
+
var mergedDateRange = dateRanges[id];
|
5418
|
+
var dateRange = new DateRange(deltaDateRanges[id].attr, mergedDateRange);
|
5419
|
+
if (dateRange.isValid) {
|
5420
|
+
dateRanges[id] = dateRange;
|
5421
|
+
if (!mergedDateRange) {
|
5422
|
+
dateRange.tagOrder += mergeCount;
|
5423
|
+
}
|
5424
|
+
} else {
|
5425
|
+
logger.warn("Ignoring invalid Playlist Delta Update DATERANGE tag: \"" + JSON.stringify(deltaDateRanges[id].attr) + "\"");
|
5426
|
+
}
|
5427
|
+
});
|
5428
|
+
}
|
5238
5429
|
return dateRanges;
|
5239
5430
|
}
|
5240
5431
|
function mapPartIntersection(oldParts, newParts, intersectionFn) {
|
@@ -5261,7 +5452,7 @@
|
|
5261
5452
|
for (var i = start; i <= end; i++) {
|
5262
5453
|
var _oldFrag = oldFrags[delta + i];
|
5263
5454
|
var _newFrag = newFrags[i];
|
5264
|
-
if (skippedSegments && !_newFrag &&
|
5455
|
+
if (skippedSegments && !_newFrag && _oldFrag) {
|
5265
5456
|
// Fill in skipped segments in delta playlist
|
5266
5457
|
_newFrag = newDetails.fragments[i] = _oldFrag;
|
5267
5458
|
}
|
@@ -5314,19 +5505,19 @@
|
|
5314
5505
|
return Math.round(reloadInterval);
|
5315
5506
|
}
|
5316
5507
|
function getFragmentWithSN(level, sn, fragCurrent) {
|
5317
|
-
|
5508
|
+
var details = level == null ? void 0 : level.details;
|
5509
|
+
if (!details) {
|
5318
5510
|
return null;
|
5319
5511
|
}
|
5320
|
-
var
|
5321
|
-
var fragment = levelDetails.fragments[sn - levelDetails.startSN];
|
5512
|
+
var fragment = details.fragments[sn - details.startSN];
|
5322
5513
|
if (fragment) {
|
5323
5514
|
return fragment;
|
5324
5515
|
}
|
5325
|
-
fragment =
|
5516
|
+
fragment = details.fragmentHint;
|
5326
5517
|
if (fragment && fragment.sn === sn) {
|
5327
5518
|
return fragment;
|
5328
5519
|
}
|
5329
|
-
if (sn <
|
5520
|
+
if (sn < details.startSN && fragCurrent && fragCurrent.sn === sn) {
|
5330
5521
|
return fragCurrent;
|
5331
5522
|
}
|
5332
5523
|
return null;
|
@@ -10872,11 +11063,10 @@
|
|
10872
11063
|
_proto.detectPartialFragments = function detectPartialFragments(data) {
|
10873
11064
|
var _this2 = this;
|
10874
11065
|
var timeRanges = this.timeRanges;
|
10875
|
-
|
10876
|
-
part = data.part;
|
10877
|
-
if (!timeRanges || frag.sn === 'initSegment') {
|
11066
|
+
if (!timeRanges || data.frag.sn === 'initSegment') {
|
10878
11067
|
return;
|
10879
11068
|
}
|
11069
|
+
var frag = data.frag;
|
10880
11070
|
var fragKey = getFragmentKey(frag);
|
10881
11071
|
var fragmentEntity = this.fragments[fragKey];
|
10882
11072
|
if (!fragmentEntity || fragmentEntity.buffered && frag.gap) {
|
@@ -10890,7 +11080,7 @@
|
|
10890
11080
|
}
|
10891
11081
|
var timeRange = timeRanges[elementaryStream];
|
10892
11082
|
var partial = isFragHint || streamInfo.partial === true;
|
10893
|
-
fragmentEntity.range[elementaryStream] = _this2.getBufferedTimes(frag, part, partial, timeRange);
|
11083
|
+
fragmentEntity.range[elementaryStream] = _this2.getBufferedTimes(frag, data.part, partial, timeRange);
|
10894
11084
|
});
|
10895
11085
|
fragmentEntity.loaded = null;
|
10896
11086
|
if (Object.keys(fragmentEntity.range).length) {
|
@@ -11043,16 +11233,14 @@
|
|
11043
11233
|
return false;
|
11044
11234
|
};
|
11045
11235
|
_proto.onFragLoaded = function onFragLoaded(event, data) {
|
11046
|
-
var frag = data.frag,
|
11047
|
-
part = data.part;
|
11048
11236
|
// don't track initsegment (for which sn is not a number)
|
11049
11237
|
// don't track frags used for bitrateTest, they're irrelevant.
|
11050
|
-
if (frag.sn === 'initSegment' || frag.bitrateTest) {
|
11238
|
+
if (data.frag.sn === 'initSegment' || data.frag.bitrateTest) {
|
11051
11239
|
return;
|
11052
11240
|
}
|
11053
|
-
|
11241
|
+
var frag = data.frag;
|
11054
11242
|
// Fragment entity `loaded` FragLoadedData is null when loading parts
|
11055
|
-
var loaded = part ? null : data;
|
11243
|
+
var loaded = data.part ? null : data;
|
11056
11244
|
var fragKey = getFragmentKey(frag);
|
11057
11245
|
this.fragments[fragKey] = {
|
11058
11246
|
body: frag,
|
@@ -13184,14 +13372,12 @@
|
|
13184
13372
|
part.stats.parsing.end = now;
|
13185
13373
|
}
|
13186
13374
|
// See if part loading should be disabled/enabled based on buffer and playback position.
|
13187
|
-
|
13188
|
-
|
13189
|
-
|
13190
|
-
|
13191
|
-
|
13192
|
-
|
13193
|
-
this.loadingParts = shouldLoadParts;
|
13194
|
-
}
|
13375
|
+
var levelDetails = this.getLevelDetails();
|
13376
|
+
var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
|
13377
|
+
var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
|
13378
|
+
if (shouldLoadParts !== this.loadingParts) {
|
13379
|
+
this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
|
13380
|
+
this.loadingParts = shouldLoadParts;
|
13195
13381
|
}
|
13196
13382
|
this.updateLevelTiming(frag, part, level, chunkMeta.partial);
|
13197
13383
|
};
|
@@ -20199,8 +20385,8 @@
|
|
20199
20385
|
};
|
20200
20386
|
_proto._handleFragmentLoadProgress = function _handleFragmentLoadProgress(data) {
|
20201
20387
|
var _frag$initSegment;
|
20202
|
-
var frag = data.frag
|
20203
|
-
|
20388
|
+
var frag = data.frag;
|
20389
|
+
var part = data.part,
|
20204
20390
|
payload = data.payload;
|
20205
20391
|
var levels = this.levels;
|
20206
20392
|
if (!levels) {
|
@@ -20540,7 +20726,7 @@
|
|
20540
20726
|
}
|
20541
20727
|
|
20542
20728
|
// Avoid buffering if backtracking this fragment
|
20543
|
-
if (video && details
|
20729
|
+
if (video && details) {
|
20544
20730
|
var prevFrag = details.fragments[frag.sn - 1 - details.startSN];
|
20545
20731
|
var isFirstFragment = frag.sn === details.startSN;
|
20546
20732
|
var isFirstInDiscontinuity = !prevFrag || frag.cc > prevFrag.cc;
|
@@ -21709,7 +21895,7 @@
|
|
21709
21895
|
* Get the video-dev/hls.js package version.
|
21710
21896
|
*/
|
21711
21897
|
function get() {
|
21712
|
-
return "1.5.12-0.canary.
|
21898
|
+
return "1.5.12-0.canary.10341";
|
21713
21899
|
}
|
21714
21900
|
}, {
|
21715
21901
|
key: "Events",
|