hls.js 1.5.17 → 1.5.19
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 +342 -268
- package/dist/hls.js.d.ts +10 -6
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +112 -91
- 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 +111 -90
- 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 +292 -222
- 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 +4 -2
- package/src/controller/base-stream-controller.ts +9 -0
- package/src/controller/buffer-controller.ts +1 -0
- package/src/controller/eme-controller.ts +184 -124
- package/src/controller/stream-controller.ts +4 -1
- package/src/hls.ts +24 -17
- package/src/loader/key-loader.ts +6 -1
- package/src/loader/level-key.ts +6 -30
- package/src/remux/mp4-remuxer.ts +11 -7
- package/src/types/component-api.ts +2 -0
- package/src/utils/level-helper.ts +37 -38
- package/src/utils/mediakeys-helper.ts +34 -1
- package/src/utils/xhr-loader.ts +52 -49
package/dist/hls.js
CHANGED
@@ -552,7 +552,7 @@
|
|
552
552
|
// Some browsers don't allow to use bind on console object anyway
|
553
553
|
// fallback to default if needed
|
554
554
|
try {
|
555
|
-
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.
|
555
|
+
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.19");
|
556
556
|
} catch (e) {
|
557
557
|
exportedLogger = fakeLogger;
|
558
558
|
}
|
@@ -1378,6 +1378,27 @@
|
|
1378
1378
|
};
|
1379
1379
|
return [baseConfig];
|
1380
1380
|
}
|
1381
|
+
function parsePlayReadyWRM(keyBytes) {
|
1382
|
+
var keyBytesUtf16 = new Uint16Array(keyBytes.buffer, keyBytes.byteOffset, keyBytes.byteLength / 2);
|
1383
|
+
var keyByteStr = String.fromCharCode.apply(null, Array.from(keyBytesUtf16));
|
1384
|
+
|
1385
|
+
// Parse Playready WRMHeader XML
|
1386
|
+
var xmlKeyBytes = keyByteStr.substring(keyByteStr.indexOf('<'), keyByteStr.length);
|
1387
|
+
var parser = new DOMParser();
|
1388
|
+
var xmlDoc = parser.parseFromString(xmlKeyBytes, 'text/xml');
|
1389
|
+
var keyData = xmlDoc.getElementsByTagName('KID')[0];
|
1390
|
+
if (keyData) {
|
1391
|
+
var keyId = keyData.childNodes[0] ? keyData.childNodes[0].nodeValue : keyData.getAttribute('VALUE');
|
1392
|
+
if (keyId) {
|
1393
|
+
var keyIdArray = base64Decode(keyId).subarray(0, 16);
|
1394
|
+
// KID value in PRO is a base64-encoded little endian GUID interpretation of UUID
|
1395
|
+
// KID value in ‘tenc’ is a big endian UUID GUID interpretation of UUID
|
1396
|
+
changeEndianness(keyIdArray);
|
1397
|
+
return keyIdArray;
|
1398
|
+
}
|
1399
|
+
}
|
1400
|
+
return null;
|
1401
|
+
}
|
1381
1402
|
|
1382
1403
|
function sliceUint8(array, start, end) {
|
1383
1404
|
// @ts-expect-error This polyfills IE11 usage of Uint8Array slice.
|
@@ -3011,6 +3032,8 @@
|
|
3011
3032
|
if (keyBytes) {
|
3012
3033
|
switch (this.keyFormat) {
|
3013
3034
|
case KeySystemFormats.WIDEVINE:
|
3035
|
+
// Setting `pssh` on this LevelKey/DecryptData allows HLS.js to generate a session using
|
3036
|
+
// the playlist-key before the "encrypted" event. (Comment out to only use "encrypted" path.)
|
3014
3037
|
this.pssh = keyBytes;
|
3015
3038
|
// In case of widevine keyID is embedded in PSSH box. Read Key ID.
|
3016
3039
|
if (keyBytes.length >= 22) {
|
@@ -3020,25 +3043,11 @@
|
|
3020
3043
|
case KeySystemFormats.PLAYREADY:
|
3021
3044
|
{
|
3022
3045
|
var PlayReadyKeySystemUUID = new Uint8Array([0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95]);
|
3046
|
+
|
3047
|
+
// Setting `pssh` on this LevelKey/DecryptData allows HLS.js to generate a session using
|
3048
|
+
// the playlist-key before the "encrypted" event. (Comment out to only use "encrypted" path.)
|
3023
3049
|
this.pssh = mp4pssh(PlayReadyKeySystemUUID, null, keyBytes);
|
3024
|
-
|
3025
|
-
var keyByteStr = String.fromCharCode.apply(null, Array.from(keyBytesUtf16));
|
3026
|
-
|
3027
|
-
// Parse Playready WRMHeader XML
|
3028
|
-
var xmlKeyBytes = keyByteStr.substring(keyByteStr.indexOf('<'), keyByteStr.length);
|
3029
|
-
var parser = new DOMParser();
|
3030
|
-
var xmlDoc = parser.parseFromString(xmlKeyBytes, 'text/xml');
|
3031
|
-
var keyData = xmlDoc.getElementsByTagName('KID')[0];
|
3032
|
-
if (keyData) {
|
3033
|
-
var keyId = keyData.childNodes[0] ? keyData.childNodes[0].nodeValue : keyData.getAttribute('VALUE');
|
3034
|
-
if (keyId) {
|
3035
|
-
var keyIdArray = base64Decode(keyId).subarray(0, 16);
|
3036
|
-
// KID value in PRO is a base64-encoded little endian GUID interpretation of UUID
|
3037
|
-
// KID value in ‘tenc’ is a big endian UUID GUID interpretation of UUID
|
3038
|
-
changeEndianness(keyIdArray);
|
3039
|
-
this.keyId = keyIdArray;
|
3040
|
-
}
|
3041
|
-
}
|
3050
|
+
this.keyId = parsePlayReadyWRM(keyBytes);
|
3042
3051
|
break;
|
3043
3052
|
}
|
3044
3053
|
default:
|
@@ -3057,15 +3066,15 @@
|
|
3057
3066
|
|
3058
3067
|
// Default behavior: assign a new keyId for each uri
|
3059
3068
|
if (!this.keyId || this.keyId.byteLength !== 16) {
|
3060
|
-
var
|
3061
|
-
if (!
|
3069
|
+
var keyId = keyUriToKeyIdMap[this.uri];
|
3070
|
+
if (!keyId) {
|
3062
3071
|
var val = Object.keys(keyUriToKeyIdMap).length % Number.MAX_SAFE_INTEGER;
|
3063
|
-
|
3064
|
-
var dv = new DataView(
|
3072
|
+
keyId = new Uint8Array(16);
|
3073
|
+
var dv = new DataView(keyId.buffer, 12, 4); // Just set the last 4 bytes
|
3065
3074
|
dv.setUint32(0, val);
|
3066
|
-
keyUriToKeyIdMap[this.uri] =
|
3075
|
+
keyUriToKeyIdMap[this.uri] = keyId;
|
3067
3076
|
}
|
3068
|
-
this.keyId =
|
3077
|
+
this.keyId = keyId;
|
3069
3078
|
}
|
3070
3079
|
return this;
|
3071
3080
|
};
|
@@ -5543,15 +5552,16 @@
|
|
5543
5552
|
delete oldDetails.fragmentHint.endPTS;
|
5544
5553
|
}
|
5545
5554
|
// check if old/new playlists have fragments in common
|
5546
|
-
// loop through overlapping SN and update startPTS
|
5547
|
-
var ccOffset = 0;
|
5555
|
+
// loop through overlapping SN and update startPTS, cc, and duration if any found
|
5548
5556
|
var PTSFrag;
|
5549
|
-
mapFragmentIntersection(oldDetails, newDetails, function (oldFrag, newFrag) {
|
5550
|
-
if (
|
5551
|
-
|
5552
|
-
|
5553
|
-
|
5554
|
-
|
5557
|
+
mapFragmentIntersection(oldDetails, newDetails, function (oldFrag, newFrag, newFragIndex, newFragments) {
|
5558
|
+
if (newDetails.skippedSegments) {
|
5559
|
+
if (newFrag.cc !== oldFrag.cc) {
|
5560
|
+
var ccOffset = oldFrag.cc - newFrag.cc;
|
5561
|
+
for (var _i = newFragIndex; _i < newFragments.length; _i++) {
|
5562
|
+
newFragments[_i].cc += ccOffset;
|
5563
|
+
}
|
5564
|
+
}
|
5555
5565
|
}
|
5556
5566
|
if (isFiniteNumber(oldFrag.startPTS) && isFiniteNumber(oldFrag.endPTS)) {
|
5557
5567
|
newFrag.start = newFrag.startPTS = oldFrag.startPTS;
|
@@ -5576,8 +5586,9 @@
|
|
5576
5586
|
currentInitSegment = oldFrag.initSegment;
|
5577
5587
|
}
|
5578
5588
|
});
|
5589
|
+
var newFragments = newDetails.fragments;
|
5579
5590
|
if (currentInitSegment) {
|
5580
|
-
var fragmentsToCheck = newDetails.fragmentHint ?
|
5591
|
+
var fragmentsToCheck = newDetails.fragmentHint ? newFragments.concat(newDetails.fragmentHint) : newFragments;
|
5581
5592
|
fragmentsToCheck.forEach(function (frag) {
|
5582
5593
|
var _currentInitSegment;
|
5583
5594
|
if (frag && (!frag.initSegment || frag.initSegment.relurl === ((_currentInitSegment = currentInitSegment) == null ? void 0 : _currentInitSegment.relurl))) {
|
@@ -5586,29 +5597,22 @@
|
|
5586
5597
|
});
|
5587
5598
|
}
|
5588
5599
|
if (newDetails.skippedSegments) {
|
5589
|
-
newDetails.deltaUpdateFailed =
|
5600
|
+
newDetails.deltaUpdateFailed = newFragments.some(function (frag) {
|
5590
5601
|
return !frag;
|
5591
5602
|
});
|
5592
5603
|
if (newDetails.deltaUpdateFailed) {
|
5593
5604
|
logger.warn('[level-helper] Previous playlist missing segments skipped in delta playlist');
|
5594
|
-
for (var
|
5595
|
-
|
5605
|
+
for (var _i2 = newDetails.skippedSegments; _i2--;) {
|
5606
|
+
newFragments.shift();
|
5607
|
+
}
|
5608
|
+
newDetails.startSN = newFragments[0].sn;
|
5609
|
+
} else {
|
5610
|
+
if (newDetails.canSkipDateRanges) {
|
5611
|
+
newDetails.dateRanges = mergeDateRanges(oldDetails.dateRanges, newDetails.dateRanges, newDetails.recentlyRemovedDateranges);
|
5596
5612
|
}
|
5597
|
-
newDetails.startSN = newDetails.fragments[0].sn;
|
5598
|
-
newDetails.startCC = newDetails.fragments[0].cc;
|
5599
|
-
} else if (newDetails.canSkipDateRanges) {
|
5600
|
-
newDetails.dateRanges = mergeDateRanges(oldDetails.dateRanges, newDetails.dateRanges, newDetails.recentlyRemovedDateranges);
|
5601
|
-
}
|
5602
|
-
}
|
5603
|
-
var newFragments = newDetails.fragments;
|
5604
|
-
if (ccOffset) {
|
5605
|
-
logger.warn('discontinuity sliding from playlist, take drift into account');
|
5606
|
-
for (var _i2 = 0; _i2 < newFragments.length; _i2++) {
|
5607
|
-
newFragments[_i2].cc += ccOffset;
|
5608
5613
|
}
|
5609
|
-
}
|
5610
|
-
if (newDetails.skippedSegments) {
|
5611
5614
|
newDetails.startCC = newDetails.fragments[0].cc;
|
5615
|
+
newDetails.endCC = newFragments[newFragments.length - 1].cc;
|
5612
5616
|
}
|
5613
5617
|
|
5614
5618
|
// Merge parts
|
@@ -5692,7 +5696,7 @@
|
|
5692
5696
|
_newFrag = newDetails.fragments[i] = _oldFrag;
|
5693
5697
|
}
|
5694
5698
|
if (_oldFrag && _newFrag) {
|
5695
|
-
intersectionFn(_oldFrag, _newFrag);
|
5699
|
+
intersectionFn(_oldFrag, _newFrag, i, newFrags);
|
5696
5700
|
}
|
5697
5701
|
}
|
5698
5702
|
}
|
@@ -9542,6 +9546,7 @@
|
|
9542
9546
|
_this.startFragRequested = false;
|
9543
9547
|
_this.decrypter = void 0;
|
9544
9548
|
_this.initPTS = [];
|
9549
|
+
_this.buffering = true;
|
9545
9550
|
_this.onvseeking = null;
|
9546
9551
|
_this.onvended = null;
|
9547
9552
|
_this.logPrefix = '';
|
@@ -9584,6 +9589,12 @@
|
|
9584
9589
|
this.clearNextTick();
|
9585
9590
|
this.state = State.STOPPED;
|
9586
9591
|
};
|
9592
|
+
_proto.pauseBuffering = function pauseBuffering() {
|
9593
|
+
this.buffering = false;
|
9594
|
+
};
|
9595
|
+
_proto.resumeBuffering = function resumeBuffering() {
|
9596
|
+
this.buffering = true;
|
9597
|
+
};
|
9587
9598
|
_proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
|
9588
9599
|
// If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
|
9589
9600
|
// of nothing loading/loaded return false
|
@@ -14030,19 +14041,23 @@
|
|
14030
14041
|
this.videoTrackConfig = undefined;
|
14031
14042
|
};
|
14032
14043
|
_proto.getVideoStartPts = function getVideoStartPts(videoSamples) {
|
14044
|
+
// Get the minimum PTS value relative to the first sample's PTS, normalized for 33-bit wrapping
|
14033
14045
|
var rolloverDetected = false;
|
14046
|
+
var firstPts = videoSamples[0].pts;
|
14034
14047
|
var startPTS = videoSamples.reduce(function (minPTS, sample) {
|
14035
|
-
var
|
14048
|
+
var pts = sample.pts;
|
14049
|
+
var delta = pts - minPTS;
|
14036
14050
|
if (delta < -4294967296) {
|
14037
14051
|
// 2^32, see PTSNormalize for reasoning, but we're hitting a rollover here, and we don't want that to impact the timeOffset calculation
|
14038
14052
|
rolloverDetected = true;
|
14039
|
-
|
14040
|
-
|
14053
|
+
pts = normalizePts(pts, firstPts);
|
14054
|
+
delta = pts - minPTS;
|
14055
|
+
}
|
14056
|
+
if (delta > 0) {
|
14041
14057
|
return minPTS;
|
14042
|
-
} else {
|
14043
|
-
return sample.pts;
|
14044
14058
|
}
|
14045
|
-
|
14059
|
+
return pts;
|
14060
|
+
}, firstPts);
|
14046
14061
|
if (rolloverDetected) {
|
14047
14062
|
logger.debug('PTS rollover detected');
|
14048
14063
|
}
|
@@ -16487,12 +16502,13 @@
|
|
16487
16502
|
trackId = this.trackId;
|
16488
16503
|
var config = hls.config;
|
16489
16504
|
|
16490
|
-
// 1. if
|
16505
|
+
// 1. if buffering is suspended
|
16506
|
+
// 2. if video not attached AND
|
16491
16507
|
// start fragment already requested OR start frag prefetch not enabled
|
16492
|
-
//
|
16508
|
+
// 3. if tracks or track not loaded and selected
|
16493
16509
|
// then exit loop
|
16494
16510
|
// => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
|
16495
|
-
if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
16511
|
+
if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
16496
16512
|
return;
|
16497
16513
|
}
|
16498
16514
|
var levelInfo = levels[trackId];
|
@@ -18529,6 +18545,7 @@
|
|
18529
18545
|
_this2.resetBuffer(type);
|
18530
18546
|
});
|
18531
18547
|
this._initSourceBuffer();
|
18548
|
+
this.hls.resumeBuffering();
|
18532
18549
|
};
|
18533
18550
|
_proto.resetBuffer = function resetBuffer(type) {
|
18534
18551
|
var sb = this.sourceBuffer[type];
|
@@ -22585,6 +22602,7 @@
|
|
22585
22602
|
*/
|
22586
22603
|
var EMEController = /*#__PURE__*/function () {
|
22587
22604
|
function EMEController(hls) {
|
22605
|
+
var _this = this;
|
22588
22606
|
this.hls = void 0;
|
22589
22607
|
this.config = void 0;
|
22590
22608
|
this.media = null;
|
@@ -22594,12 +22612,161 @@
|
|
22594
22612
|
this.mediaKeySessions = [];
|
22595
22613
|
this.keyIdToKeySessionPromise = {};
|
22596
22614
|
this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
22597
|
-
this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
|
22598
|
-
this.onWaitingForKey = this._onWaitingForKey.bind(this);
|
22599
22615
|
this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
|
22600
22616
|
this.log = logger.log.bind(logger, LOGGER_PREFIX);
|
22601
22617
|
this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
|
22602
22618
|
this.error = logger.error.bind(logger, LOGGER_PREFIX);
|
22619
|
+
this.onMediaEncrypted = function (event) {
|
22620
|
+
var initDataType = event.initDataType,
|
22621
|
+
initData = event.initData;
|
22622
|
+
var logMessage = "\"" + event.type + "\" event: init data type: \"" + initDataType + "\"";
|
22623
|
+
_this.debug(logMessage);
|
22624
|
+
|
22625
|
+
// Ignore event when initData is null
|
22626
|
+
if (initData === null) {
|
22627
|
+
return;
|
22628
|
+
}
|
22629
|
+
if (!_this.keyFormatPromise) {
|
22630
|
+
var keySystems = Object.keys(_this.keySystemAccessPromises);
|
22631
|
+
if (!keySystems.length) {
|
22632
|
+
keySystems = getKeySystemsForConfig(_this.config);
|
22633
|
+
}
|
22634
|
+
var keyFormats = keySystems.map(keySystemDomainToKeySystemFormat).filter(function (k) {
|
22635
|
+
return !!k;
|
22636
|
+
});
|
22637
|
+
_this.keyFormatPromise = _this.getKeyFormatPromise(keyFormats);
|
22638
|
+
}
|
22639
|
+
_this.keyFormatPromise.then(function (keySystemFormat) {
|
22640
|
+
var keySystem = keySystemFormatToKeySystemDomain(keySystemFormat);
|
22641
|
+
var keyId;
|
22642
|
+
var keySystemDomain;
|
22643
|
+
if (initDataType === 'sinf') {
|
22644
|
+
if (keySystem !== KeySystems.FAIRPLAY) {
|
22645
|
+
_this.warn("Ignoring unexpected \"" + event.type + "\" event with init data type: \"" + initDataType + "\" for selected key-system " + keySystem);
|
22646
|
+
return;
|
22647
|
+
}
|
22648
|
+
// Match sinf keyId to playlist skd://keyId=
|
22649
|
+
var json = bin2str(new Uint8Array(initData));
|
22650
|
+
try {
|
22651
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
22652
|
+
var tenc = parseSinf(sinf);
|
22653
|
+
if (!tenc) {
|
22654
|
+
throw new Error("'schm' box missing or not cbcs/cenc with schi > tenc");
|
22655
|
+
}
|
22656
|
+
keyId = tenc.subarray(8, 24);
|
22657
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
22658
|
+
} catch (error) {
|
22659
|
+
_this.warn(logMessage + " Failed to parse sinf: " + error);
|
22660
|
+
return;
|
22661
|
+
}
|
22662
|
+
} else {
|
22663
|
+
if (keySystem !== KeySystems.WIDEVINE && keySystem !== KeySystems.PLAYREADY) {
|
22664
|
+
_this.warn("Ignoring unexpected \"" + event.type + "\" event with init data type: \"" + initDataType + "\" for selected key-system " + keySystem);
|
22665
|
+
return;
|
22666
|
+
}
|
22667
|
+
// Support Widevine/PlayReady clear-lead key-session creation (otherwise depend on playlist keys)
|
22668
|
+
var psshResults = parseMultiPssh(initData);
|
22669
|
+
var psshInfos = psshResults.filter(function (pssh) {
|
22670
|
+
return !!pssh.systemId && keySystemIdToKeySystemDomain(pssh.systemId) === keySystem;
|
22671
|
+
});
|
22672
|
+
if (psshInfos.length > 1) {
|
22673
|
+
_this.warn(logMessage + " Using first of " + psshInfos.length + " pssh found for selected key-system " + keySystem);
|
22674
|
+
}
|
22675
|
+
var psshInfo = psshInfos[0];
|
22676
|
+
if (!psshInfo) {
|
22677
|
+
if (psshResults.length === 0 || psshResults.some(function (pssh) {
|
22678
|
+
return !pssh.systemId;
|
22679
|
+
})) {
|
22680
|
+
_this.warn(logMessage + " contains incomplete or invalid pssh data");
|
22681
|
+
} else {
|
22682
|
+
_this.log("ignoring " + logMessage + " for " + psshResults.map(function (pssh) {
|
22683
|
+
return keySystemIdToKeySystemDomain(pssh.systemId);
|
22684
|
+
}).join(',') + " pssh data in favor of playlist keys");
|
22685
|
+
}
|
22686
|
+
return;
|
22687
|
+
}
|
22688
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22689
|
+
if (psshInfo.version === 0 && psshInfo.data) {
|
22690
|
+
if (keySystemDomain === KeySystems.WIDEVINE) {
|
22691
|
+
var offset = psshInfo.data.length - 22;
|
22692
|
+
keyId = psshInfo.data.subarray(offset, offset + 16);
|
22693
|
+
} else if (keySystemDomain === KeySystems.PLAYREADY) {
|
22694
|
+
keyId = parsePlayReadyWRM(psshInfo.data);
|
22695
|
+
}
|
22696
|
+
}
|
22697
|
+
}
|
22698
|
+
if (!keySystemDomain || !keyId) {
|
22699
|
+
_this.log("Unable to handle " + logMessage + " with key-system " + keySystem);
|
22700
|
+
return;
|
22701
|
+
}
|
22702
|
+
var keyIdHex = Hex.hexDump(keyId);
|
22703
|
+
var keyIdToKeySessionPromise = _this.keyIdToKeySessionPromise,
|
22704
|
+
mediaKeySessions = _this.mediaKeySessions;
|
22705
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22706
|
+
var _loop = function _loop() {
|
22707
|
+
// Match playlist key
|
22708
|
+
var keyContext = mediaKeySessions[i];
|
22709
|
+
var decryptdata = keyContext.decryptdata;
|
22710
|
+
if (!decryptdata.keyId) {
|
22711
|
+
return 0; // continue
|
22712
|
+
}
|
22713
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22714
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22715
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22716
|
+
if (decryptdata.pssh) {
|
22717
|
+
return 1; // break
|
22718
|
+
}
|
22719
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22720
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22721
|
+
decryptdata.keyId = keyId;
|
22722
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22723
|
+
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22724
|
+
});
|
22725
|
+
keySessionContextPromise.catch(function (error) {
|
22726
|
+
return _this.handleError(error);
|
22727
|
+
});
|
22728
|
+
return 1; // break
|
22729
|
+
}
|
22730
|
+
},
|
22731
|
+
_ret;
|
22732
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22733
|
+
_ret = _loop();
|
22734
|
+
if (_ret === 0) continue;
|
22735
|
+
if (_ret === 1) break;
|
22736
|
+
}
|
22737
|
+
if (!keySessionContextPromise) {
|
22738
|
+
if (keySystemDomain !== keySystem) {
|
22739
|
+
_this.log("Ignoring \"" + logMessage + "\" with " + keySystemDomain + " init data for selected key-system " + keySystem);
|
22740
|
+
return;
|
22741
|
+
}
|
22742
|
+
// "Clear-lead" (misc key not encountered in playlist)
|
22743
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
22744
|
+
var _keySystemToKeySystem;
|
22745
|
+
var keySystem = _ref.keySystem,
|
22746
|
+
mediaKeys = _ref.mediaKeys;
|
22747
|
+
_this.throwIfDestroyed();
|
22748
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22749
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22750
|
+
decryptdata.keyId = keyId;
|
22751
|
+
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22752
|
+
_this.throwIfDestroyed();
|
22753
|
+
var keySessionContext = _this.createMediaKeySessionContext({
|
22754
|
+
decryptdata: decryptdata,
|
22755
|
+
keySystem: keySystem,
|
22756
|
+
mediaKeys: mediaKeys
|
22757
|
+
});
|
22758
|
+
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22759
|
+
});
|
22760
|
+
});
|
22761
|
+
keySessionContextPromise.catch(function (error) {
|
22762
|
+
return _this.handleError(error);
|
22763
|
+
});
|
22764
|
+
}
|
22765
|
+
});
|
22766
|
+
};
|
22767
|
+
this.onWaitingForKey = function (event) {
|
22768
|
+
_this.log("\"" + event.type + "\" event");
|
22769
|
+
};
|
22603
22770
|
this.hls = hls;
|
22604
22771
|
this.config = hls.config;
|
22605
22772
|
this.registerListeners();
|
@@ -22614,9 +22781,9 @@
|
|
22614
22781
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
22615
22782
|
config.drmSystems = config.drmSystemOptions = {};
|
22616
22783
|
// @ts-ignore
|
22617
|
-
this.hls = this.
|
22784
|
+
this.hls = this.config = this.keyIdToKeySessionPromise = null;
|
22618
22785
|
// @ts-ignore
|
22619
|
-
this.
|
22786
|
+
this.onMediaEncrypted = this.onWaitingForKey = null;
|
22620
22787
|
};
|
22621
22788
|
_proto.registerListeners = function registerListeners() {
|
22622
22789
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -22643,7 +22810,13 @@
|
|
22643
22810
|
if (keySystem === KeySystems.WIDEVINE && widevineLicenseUrl) {
|
22644
22811
|
return widevineLicenseUrl;
|
22645
22812
|
}
|
22646
|
-
|
22813
|
+
};
|
22814
|
+
_proto.getLicenseServerUrlOrThrow = function getLicenseServerUrlOrThrow(keySystem) {
|
22815
|
+
var url = this.getLicenseServerUrl(keySystem);
|
22816
|
+
if (url === undefined) {
|
22817
|
+
throw new Error("no license server URL configured for key-system \"" + keySystem + "\"");
|
22818
|
+
}
|
22819
|
+
return url;
|
22647
22820
|
};
|
22648
22821
|
_proto.getServerCertificateUrl = function getServerCertificateUrl(keySystem) {
|
22649
22822
|
var drmSystems = this.config.drmSystems;
|
@@ -22655,7 +22828,7 @@
|
|
22655
22828
|
}
|
22656
22829
|
};
|
22657
22830
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
22658
|
-
var
|
22831
|
+
var _this2 = this;
|
22659
22832
|
var levels = this.hls.levels;
|
22660
22833
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
22661
22834
|
return !!value && a.indexOf(value) === i;
|
@@ -22672,7 +22845,7 @@
|
|
22672
22845
|
return new Promise(function (resolve, reject) {
|
22673
22846
|
var attempt = function attempt(keySystems) {
|
22674
22847
|
var keySystem = keySystems.shift();
|
22675
|
-
|
22848
|
+
_this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
22676
22849
|
return resolve({
|
22677
22850
|
keySystem: keySystem,
|
22678
22851
|
mediaKeys: mediaKeys
|
@@ -22707,7 +22880,7 @@
|
|
22707
22880
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
22708
22881
|
};
|
22709
22882
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
22710
|
-
var
|
22883
|
+
var _this3 = this;
|
22711
22884
|
// This can throw, but is caught in event handler callpath
|
22712
22885
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
22713
22886
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -22719,23 +22892,23 @@
|
|
22719
22892
|
keySystemAccess: keySystemAccess
|
22720
22893
|
};
|
22721
22894
|
keySystemAccess.catch(function (error) {
|
22722
|
-
|
22895
|
+
_this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
22723
22896
|
});
|
22724
22897
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
22725
|
-
|
22726
|
-
var certificateRequest =
|
22727
|
-
|
22898
|
+
_this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
22899
|
+
var certificateRequest = _this3.fetchServerCertificate(keySystem);
|
22900
|
+
_this3.log("Create media-keys for \"" + keySystem + "\"");
|
22728
22901
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
22729
|
-
|
22902
|
+
_this3.log("Media-keys created for \"" + keySystem + "\"");
|
22730
22903
|
return certificateRequest.then(function (certificate) {
|
22731
22904
|
if (certificate) {
|
22732
|
-
return
|
22905
|
+
return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
22733
22906
|
}
|
22734
22907
|
return mediaKeys;
|
22735
22908
|
});
|
22736
22909
|
});
|
22737
22910
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
22738
|
-
|
22911
|
+
_this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
22739
22912
|
});
|
22740
22913
|
return _keySystemAccessPromises.mediaKeys;
|
22741
22914
|
});
|
@@ -22744,10 +22917,10 @@
|
|
22744
22917
|
return keySystemAccessPromises.mediaKeys;
|
22745
22918
|
});
|
22746
22919
|
};
|
22747
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
22748
|
-
var decryptdata =
|
22749
|
-
keySystem =
|
22750
|
-
mediaKeys =
|
22920
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
|
22921
|
+
var decryptdata = _ref2.decryptdata,
|
22922
|
+
keySystem = _ref2.keySystem,
|
22923
|
+
mediaKeys = _ref2.mediaKeys;
|
22751
22924
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
22752
22925
|
var mediaKeysSession = mediaKeys.createSession();
|
22753
22926
|
var mediaKeySessionContext = {
|
@@ -22796,14 +22969,14 @@
|
|
22796
22969
|
return this.keyFormatPromise;
|
22797
22970
|
};
|
22798
22971
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
22799
|
-
var
|
22972
|
+
var _this4 = this;
|
22800
22973
|
return new Promise(function (resolve, reject) {
|
22801
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
22974
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
|
22802
22975
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
22803
22976
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
22804
22977
|
});
|
22805
|
-
return
|
22806
|
-
var keySystem =
|
22978
|
+
return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
|
22979
|
+
var keySystem = _ref3.keySystem;
|
22807
22980
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
22808
22981
|
if (keySystemFormat) {
|
22809
22982
|
resolve(keySystemFormat);
|
@@ -22814,31 +22987,31 @@
|
|
22814
22987
|
});
|
22815
22988
|
};
|
22816
22989
|
_proto.loadKey = function loadKey(data) {
|
22817
|
-
var
|
22990
|
+
var _this5 = this;
|
22818
22991
|
var decryptdata = data.keyInfo.decryptdata;
|
22819
22992
|
var keyId = this.getKeyIdString(decryptdata);
|
22820
22993
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
22821
22994
|
this.log("Starting session for key " + keyDetails);
|
22822
22995
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
22823
22996
|
if (!keySessionContextPromise) {
|
22824
|
-
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (
|
22825
|
-
var keySystem =
|
22826
|
-
mediaKeys =
|
22827
|
-
|
22828
|
-
|
22829
|
-
return
|
22830
|
-
|
22831
|
-
var keySessionContext =
|
22997
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
|
22998
|
+
var keySystem = _ref4.keySystem,
|
22999
|
+
mediaKeys = _ref4.mediaKeys;
|
23000
|
+
_this5.throwIfDestroyed();
|
23001
|
+
_this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
23002
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23003
|
+
_this5.throwIfDestroyed();
|
23004
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22832
23005
|
keySystem: keySystem,
|
22833
23006
|
mediaKeys: mediaKeys,
|
22834
23007
|
decryptdata: decryptdata
|
22835
23008
|
});
|
22836
23009
|
var scheme = 'cenc';
|
22837
|
-
return
|
23010
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
22838
23011
|
});
|
22839
23012
|
});
|
22840
23013
|
keySessionContextPromise.catch(function (error) {
|
22841
|
-
return
|
23014
|
+
return _this5.handleError(error);
|
22842
23015
|
});
|
22843
23016
|
}
|
22844
23017
|
return keySessionContextPromise;
|
@@ -22889,121 +23062,6 @@
|
|
22889
23062
|
}
|
22890
23063
|
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22891
23064
|
};
|
22892
|
-
_proto._onMediaEncrypted = function _onMediaEncrypted(event) {
|
22893
|
-
var _this5 = this;
|
22894
|
-
var initDataType = event.initDataType,
|
22895
|
-
initData = event.initData;
|
22896
|
-
var logMessage = "\"" + event.type + "\" event: init data type: \"" + initDataType + "\"";
|
22897
|
-
this.debug(logMessage);
|
22898
|
-
|
22899
|
-
// Ignore event when initData is null
|
22900
|
-
if (initData === null) {
|
22901
|
-
return;
|
22902
|
-
}
|
22903
|
-
var keyId;
|
22904
|
-
var keySystemDomain;
|
22905
|
-
if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22906
|
-
// Match sinf keyId to playlist skd://keyId=
|
22907
|
-
var json = bin2str(new Uint8Array(initData));
|
22908
|
-
try {
|
22909
|
-
var sinf = base64Decode(JSON.parse(json).sinf);
|
22910
|
-
var tenc = parseSinf(new Uint8Array(sinf));
|
22911
|
-
if (!tenc) {
|
22912
|
-
throw new Error("'schm' box missing or not cbcs/cenc with schi > tenc");
|
22913
|
-
}
|
22914
|
-
keyId = tenc.subarray(8, 24);
|
22915
|
-
keySystemDomain = KeySystems.FAIRPLAY;
|
22916
|
-
} catch (error) {
|
22917
|
-
this.warn(logMessage + " Failed to parse sinf: " + error);
|
22918
|
-
return;
|
22919
|
-
}
|
22920
|
-
} else {
|
22921
|
-
// Support Widevine clear-lead key-session creation (otherwise depend on playlist keys)
|
22922
|
-
var psshResults = parseMultiPssh(initData);
|
22923
|
-
var psshInfo = psshResults.filter(function (pssh) {
|
22924
|
-
return pssh.systemId === KeySystemIds.WIDEVINE;
|
22925
|
-
})[0];
|
22926
|
-
if (!psshInfo) {
|
22927
|
-
if (psshResults.length === 0 || psshResults.some(function (pssh) {
|
22928
|
-
return !pssh.systemId;
|
22929
|
-
})) {
|
22930
|
-
this.warn(logMessage + " contains incomplete or invalid pssh data");
|
22931
|
-
} else {
|
22932
|
-
this.log("ignoring " + logMessage + " for " + psshResults.map(function (pssh) {
|
22933
|
-
return keySystemIdToKeySystemDomain(pssh.systemId);
|
22934
|
-
}).join(',') + " pssh data in favor of playlist keys");
|
22935
|
-
}
|
22936
|
-
return;
|
22937
|
-
}
|
22938
|
-
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22939
|
-
if (psshInfo.version === 0 && psshInfo.data) {
|
22940
|
-
var offset = psshInfo.data.length - 22;
|
22941
|
-
keyId = psshInfo.data.subarray(offset, offset + 16);
|
22942
|
-
}
|
22943
|
-
}
|
22944
|
-
if (!keySystemDomain || !keyId) {
|
22945
|
-
return;
|
22946
|
-
}
|
22947
|
-
var keyIdHex = Hex.hexDump(keyId);
|
22948
|
-
var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
|
22949
|
-
mediaKeySessions = this.mediaKeySessions;
|
22950
|
-
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22951
|
-
var _loop = function _loop() {
|
22952
|
-
// Match playlist key
|
22953
|
-
var keyContext = mediaKeySessions[i];
|
22954
|
-
var decryptdata = keyContext.decryptdata;
|
22955
|
-
if (!decryptdata.keyId) {
|
22956
|
-
return 0; // continue
|
22957
|
-
}
|
22958
|
-
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22959
|
-
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22960
|
-
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22961
|
-
if (decryptdata.pssh) {
|
22962
|
-
return 1; // break
|
22963
|
-
}
|
22964
|
-
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22965
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22966
|
-
decryptdata.keyId = keyId;
|
22967
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22968
|
-
return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22969
|
-
});
|
22970
|
-
return 1; // break
|
22971
|
-
}
|
22972
|
-
},
|
22973
|
-
_ret;
|
22974
|
-
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22975
|
-
_ret = _loop();
|
22976
|
-
if (_ret === 0) continue;
|
22977
|
-
if (_ret === 1) break;
|
22978
|
-
}
|
22979
|
-
if (!keySessionContextPromise) {
|
22980
|
-
// Clear-lead key (not encountered in playlist)
|
22981
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
|
22982
|
-
var _keySystemToKeySystem;
|
22983
|
-
var keySystem = _ref4.keySystem,
|
22984
|
-
mediaKeys = _ref4.mediaKeys;
|
22985
|
-
_this5.throwIfDestroyed();
|
22986
|
-
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22987
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22988
|
-
decryptdata.keyId = keyId;
|
22989
|
-
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22990
|
-
_this5.throwIfDestroyed();
|
22991
|
-
var keySessionContext = _this5.createMediaKeySessionContext({
|
22992
|
-
decryptdata: decryptdata,
|
22993
|
-
keySystem: keySystem,
|
22994
|
-
mediaKeys: mediaKeys
|
22995
|
-
});
|
22996
|
-
return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22997
|
-
});
|
22998
|
-
});
|
22999
|
-
}
|
23000
|
-
keySessionContextPromise.catch(function (error) {
|
23001
|
-
return _this5.handleError(error);
|
23002
|
-
});
|
23003
|
-
};
|
23004
|
-
_proto._onWaitingForKey = function _onWaitingForKey(event) {
|
23005
|
-
this.log("\"" + event.type + "\" event");
|
23006
|
-
};
|
23007
23065
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
23008
23066
|
var _this6 = this;
|
23009
23067
|
var queue = this.setMediaKeysQueue.slice();
|
@@ -23306,7 +23364,7 @@
|
|
23306
23364
|
var _this12 = this;
|
23307
23365
|
var keyLoadPolicy = this.config.keyLoadPolicy.default;
|
23308
23366
|
return new Promise(function (resolve, reject) {
|
23309
|
-
var url = _this12.
|
23367
|
+
var url = _this12.getLicenseServerUrlOrThrow(keySessionContext.keySystem);
|
23310
23368
|
_this12.log("Sending license request to URL: " + url);
|
23311
23369
|
var xhr = new XMLHttpRequest();
|
23312
23370
|
xhr.responseType = 'arraybuffer';
|
@@ -23375,6 +23433,8 @@
|
|
23375
23433
|
|
23376
23434
|
// keep reference of media
|
23377
23435
|
this.media = media;
|
23436
|
+
media.removeEventListener('encrypted', this.onMediaEncrypted);
|
23437
|
+
media.removeEventListener('waitingforkey', this.onWaitingForKey);
|
23378
23438
|
media.addEventListener('encrypted', this.onMediaEncrypted);
|
23379
23439
|
media.addEventListener('waitingforkey', this.onWaitingForKey);
|
23380
23440
|
};
|
@@ -25370,47 +25430,51 @@
|
|
25370
25430
|
xhr.onprogress = null;
|
25371
25431
|
var _status = xhr.status;
|
25372
25432
|
// http status between 200 to 299 are all successful
|
25373
|
-
var
|
25374
|
-
if (_status >= 200 && _status < 300
|
25375
|
-
|
25376
|
-
|
25377
|
-
|
25378
|
-
|
25379
|
-
|
25380
|
-
|
25381
|
-
|
25382
|
-
|
25383
|
-
|
25384
|
-
|
25385
|
-
onProgress
|
25386
|
-
|
25387
|
-
|
25433
|
+
var useResponseText = xhr.responseType === 'text' ? xhr.responseText : null;
|
25434
|
+
if (_status >= 200 && _status < 300) {
|
25435
|
+
var data = useResponseText != null ? useResponseText : xhr.response;
|
25436
|
+
if (data != null) {
|
25437
|
+
stats.loading.end = Math.max(self.performance.now(), stats.loading.first);
|
25438
|
+
var len = xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;
|
25439
|
+
stats.loaded = stats.total = len;
|
25440
|
+
stats.bwEstimate = stats.total * 8000 / (stats.loading.end - stats.loading.first);
|
25441
|
+
if (!this.callbacks) {
|
25442
|
+
return;
|
25443
|
+
}
|
25444
|
+
var onProgress = this.callbacks.onProgress;
|
25445
|
+
if (onProgress) {
|
25446
|
+
onProgress(stats, context, data, xhr);
|
25447
|
+
}
|
25448
|
+
if (!this.callbacks) {
|
25449
|
+
return;
|
25450
|
+
}
|
25451
|
+
var _response = {
|
25452
|
+
url: xhr.responseURL,
|
25453
|
+
data: data,
|
25454
|
+
code: _status
|
25455
|
+
};
|
25456
|
+
this.callbacks.onSuccess(_response, stats, context, xhr);
|
25388
25457
|
return;
|
25389
25458
|
}
|
25390
|
-
|
25391
|
-
|
25392
|
-
|
25393
|
-
|
25394
|
-
|
25395
|
-
|
25459
|
+
}
|
25460
|
+
|
25461
|
+
// Handle bad status or nullish response
|
25462
|
+
var retryConfig = config.loadPolicy.errorRetry;
|
25463
|
+
var retryCount = stats.retry;
|
25464
|
+
// if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
|
25465
|
+
var response = {
|
25466
|
+
url: context.url,
|
25467
|
+
data: undefined,
|
25468
|
+
code: _status
|
25469
|
+
};
|
25470
|
+
if (shouldRetry(retryConfig, retryCount, false, response)) {
|
25471
|
+
this.retry(retryConfig);
|
25396
25472
|
} else {
|
25397
|
-
|
25398
|
-
|
25399
|
-
|
25400
|
-
|
25401
|
-
|
25402
|
-
data: undefined,
|
25403
|
-
code: _status
|
25404
|
-
};
|
25405
|
-
if (shouldRetry(retryConfig, retryCount, false, _response)) {
|
25406
|
-
this.retry(retryConfig);
|
25407
|
-
} else {
|
25408
|
-
logger.error(_status + " while loading " + context.url);
|
25409
|
-
this.callbacks.onError({
|
25410
|
-
code: _status,
|
25411
|
-
text: xhr.statusText
|
25412
|
-
}, context, xhr, stats);
|
25413
|
-
}
|
25473
|
+
logger.error(_status + " while loading " + context.url);
|
25474
|
+
this.callbacks.onError({
|
25475
|
+
code: _status,
|
25476
|
+
text: xhr.statusText
|
25477
|
+
}, context, xhr, stats);
|
25414
25478
|
}
|
25415
25479
|
}
|
25416
25480
|
}
|
@@ -26790,7 +26854,7 @@
|
|
26790
26854
|
};
|
26791
26855
|
_proto.load = function load(frag) {
|
26792
26856
|
var _this2 = this;
|
26793
|
-
if (!frag.decryptdata && frag.encrypted && this.emeController) {
|
26857
|
+
if (!frag.decryptdata && frag.encrypted && this.emeController && this.config.emeEnabled) {
|
26794
26858
|
// Multiple keys, but none selected, resolve in eme-controller
|
26795
26859
|
return this.emeController.selectKeySystemFormat(frag).then(function (keySystemFormat) {
|
26796
26860
|
return _this2.loadInternal(frag, keySystemFormat);
|
@@ -27472,7 +27536,7 @@
|
|
27472
27536
|
if (this.altAudio && this.audioOnly) {
|
27473
27537
|
return;
|
27474
27538
|
}
|
27475
|
-
var level = hls.nextLoadLevel;
|
27539
|
+
var level = this.buffering ? hls.nextLoadLevel : hls.loadLevel;
|
27476
27540
|
if (!(levels != null && levels[level])) {
|
27477
27541
|
return;
|
27478
27542
|
}
|
@@ -27494,6 +27558,9 @@
|
|
27494
27558
|
this.state = State.ENDED;
|
27495
27559
|
return;
|
27496
27560
|
}
|
27561
|
+
if (!this.buffering) {
|
27562
|
+
return;
|
27563
|
+
}
|
27497
27564
|
|
27498
27565
|
// set next load level : this will trigger a playlist load if needed
|
27499
27566
|
if (hls.loadLevel !== level && hls.manualLevel === -1) {
|
@@ -28702,9 +28769,13 @@
|
|
28702
28769
|
}
|
28703
28770
|
logger.log("startLoad(" + startPosition + ")");
|
28704
28771
|
this.started = true;
|
28705
|
-
this.
|
28706
|
-
|
28707
|
-
|
28772
|
+
this.resumeBuffering();
|
28773
|
+
for (var i = 0; i < this.networkControllers.length; i++) {
|
28774
|
+
this.networkControllers[i].startLoad(startPosition);
|
28775
|
+
if (!this.started || !this.networkControllers) {
|
28776
|
+
break;
|
28777
|
+
}
|
28778
|
+
}
|
28708
28779
|
}
|
28709
28780
|
|
28710
28781
|
/**
|
@@ -28713,32 +28784,35 @@
|
|
28713
28784
|
_proto.stopLoad = function stopLoad() {
|
28714
28785
|
logger.log('stopLoad');
|
28715
28786
|
this.started = false;
|
28716
|
-
this.networkControllers.
|
28717
|
-
|
28718
|
-
|
28787
|
+
for (var i = 0; i < this.networkControllers.length; i++) {
|
28788
|
+
this.networkControllers[i].stopLoad();
|
28789
|
+
if (this.started || !this.networkControllers) {
|
28790
|
+
break;
|
28791
|
+
}
|
28792
|
+
}
|
28719
28793
|
}
|
28720
28794
|
|
28721
28795
|
/**
|
28722
|
-
* Resumes stream controller segment loading
|
28796
|
+
* Resumes stream controller segment loading after `pauseBuffering` has been called.
|
28723
28797
|
*/;
|
28724
28798
|
_proto.resumeBuffering = function resumeBuffering() {
|
28725
|
-
|
28726
|
-
|
28727
|
-
|
28728
|
-
|
28729
|
-
|
28730
|
-
|
28731
|
-
}
|
28799
|
+
logger.log("resume buffering");
|
28800
|
+
this.networkControllers.forEach(function (controller) {
|
28801
|
+
if (controller.resumeBuffering) {
|
28802
|
+
controller.resumeBuffering();
|
28803
|
+
}
|
28804
|
+
});
|
28732
28805
|
}
|
28733
28806
|
|
28734
28807
|
/**
|
28735
|
-
*
|
28808
|
+
* Prevents stream controller from loading new segments until `resumeBuffering` is called.
|
28736
28809
|
* This allows for media buffering to be paused without interupting playlist loading.
|
28737
28810
|
*/;
|
28738
28811
|
_proto.pauseBuffering = function pauseBuffering() {
|
28812
|
+
logger.log("pause buffering");
|
28739
28813
|
this.networkControllers.forEach(function (controller) {
|
28740
|
-
if (
|
28741
|
-
controller.
|
28814
|
+
if (controller.pauseBuffering) {
|
28815
|
+
controller.pauseBuffering();
|
28742
28816
|
}
|
28743
28817
|
});
|
28744
28818
|
}
|
@@ -29295,7 +29369,7 @@
|
|
29295
29369
|
* Get the video-dev/hls.js package version.
|
29296
29370
|
*/
|
29297
29371
|
function get() {
|
29298
|
-
return "1.5.
|
29372
|
+
return "1.5.19";
|
29299
29373
|
}
|
29300
29374
|
}, {
|
29301
29375
|
key: "Events",
|