hls.js 1.5.2-0.canary.9924 → 1.5.2
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-demo.js +0 -5
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +686 -762
- package/dist/hls.js.d.ts +47 -49
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +471 -563
- 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 +329 -409
- 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 +500 -559
- 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 +9 -9
- package/src/config.ts +2 -3
- package/src/controller/abr-controller.ts +22 -23
- package/src/controller/audio-stream-controller.ts +14 -11
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +7 -7
- package/src/controller/base-stream-controller.ts +29 -42
- package/src/controller/buffer-controller.ts +11 -10
- package/src/controller/cap-level-controller.ts +2 -1
- package/src/controller/content-steering-controller.ts +6 -8
- package/src/controller/eme-controller.ts +22 -9
- package/src/controller/error-controller.ts +8 -6
- package/src/controller/fps-controller.ts +3 -2
- package/src/controller/gap-controller.ts +10 -16
- package/src/controller/latency-controller.ts +11 -9
- package/src/controller/level-controller.ts +19 -8
- package/src/controller/stream-controller.ts +29 -20
- package/src/controller/subtitle-stream-controller.ts +14 -13
- package/src/controller/subtitle-track-controller.ts +3 -5
- package/src/controller/timeline-controller.ts +30 -23
- package/src/crypt/aes-crypto.ts +2 -21
- package/src/crypt/decrypter.ts +18 -32
- package/src/crypt/fast-aes-key.ts +5 -24
- package/src/demux/audio/adts.ts +4 -9
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +12 -4
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +3 -16
- package/src/demux/tsdemuxer.ts +17 -12
- package/src/hls.ts +20 -32
- package/src/loader/fragment-loader.ts +2 -9
- package/src/loader/key-loader.ts +0 -2
- package/src/loader/level-key.ts +9 -10
- package/src/remux/mp4-remuxer.ts +3 -4
- package/src/task-loop.ts +2 -5
- package/src/types/demuxer.ts +0 -1
- package/src/utils/codecs.ts +4 -33
- package/src/utils/logger.ts +24 -53
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/utils/encryption-methods-util.ts +0 -21
package/dist/hls.js
CHANGED
@@ -507,21 +507,6 @@
|
|
507
507
|
return ErrorDetails;
|
508
508
|
}({});
|
509
509
|
|
510
|
-
var Logger = function Logger(label, logger) {
|
511
|
-
this.trace = void 0;
|
512
|
-
this.debug = void 0;
|
513
|
-
this.log = void 0;
|
514
|
-
this.warn = void 0;
|
515
|
-
this.info = void 0;
|
516
|
-
this.error = void 0;
|
517
|
-
var lb = "[" + label + "]:";
|
518
|
-
this.trace = noop;
|
519
|
-
this.debug = logger.debug.bind(null, lb);
|
520
|
-
this.log = logger.log.bind(null, lb);
|
521
|
-
this.warn = logger.warn.bind(null, lb);
|
522
|
-
this.info = logger.info.bind(null, lb);
|
523
|
-
this.error = logger.error.bind(null, lb);
|
524
|
-
};
|
525
510
|
var noop = function noop() {};
|
526
511
|
var fakeLogger = {
|
527
512
|
trace: noop,
|
@@ -531,9 +516,7 @@
|
|
531
516
|
info: noop,
|
532
517
|
error: noop
|
533
518
|
};
|
534
|
-
|
535
|
-
return _extends({}, fakeLogger);
|
536
|
-
}
|
519
|
+
var exportedLogger = fakeLogger;
|
537
520
|
|
538
521
|
// let lastCallTime;
|
539
522
|
// function formatMsgWithTimeInfo(type, msg) {
|
@@ -544,36 +527,38 @@
|
|
544
527
|
// return msg;
|
545
528
|
// }
|
546
529
|
|
547
|
-
function consolePrintFn(type
|
530
|
+
function consolePrintFn(type) {
|
548
531
|
var func = self.console[type];
|
549
|
-
|
532
|
+
if (func) {
|
533
|
+
return func.bind(self.console, "[" + type + "] >");
|
534
|
+
}
|
535
|
+
return noop;
|
550
536
|
}
|
551
|
-
function
|
552
|
-
|
537
|
+
function exportLoggerFunctions(debugConfig) {
|
538
|
+
for (var _len = arguments.length, functions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
539
|
+
functions[_key - 1] = arguments[_key];
|
540
|
+
}
|
541
|
+
functions.forEach(function (type) {
|
542
|
+
exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);
|
543
|
+
});
|
553
544
|
}
|
554
|
-
|
555
|
-
function enableLogs(debugConfig, context, id) {
|
545
|
+
function enableLogs(debugConfig, id) {
|
556
546
|
// check that console is available
|
557
|
-
var newLogger = createLogger();
|
558
547
|
if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
|
559
|
-
|
548
|
+
exportLoggerFunctions(debugConfig,
|
560
549
|
// Remove out from list here to hard-disable a log-level
|
561
550
|
// 'trace',
|
562
|
-
'debug', 'log', 'info', 'warn', 'error'
|
563
|
-
keys.forEach(function (key) {
|
564
|
-
newLogger[key] = getLoggerFn(key, debugConfig, id);
|
565
|
-
});
|
551
|
+
'debug', 'log', 'info', 'warn', 'error');
|
566
552
|
// Some browsers don't allow to use bind on console object anyway
|
567
553
|
// fallback to default if needed
|
568
554
|
try {
|
569
|
-
|
555
|
+
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.2");
|
570
556
|
} catch (e) {
|
571
|
-
|
572
|
-
return createLogger();
|
557
|
+
exportedLogger = fakeLogger;
|
573
558
|
}
|
559
|
+
} else {
|
560
|
+
exportedLogger = fakeLogger;
|
574
561
|
}
|
575
|
-
exportedLogger = newLogger;
|
576
|
-
return newLogger;
|
577
562
|
}
|
578
563
|
var logger = exportedLogger;
|
579
564
|
|
@@ -1268,26 +1253,6 @@
|
|
1268
1253
|
});
|
1269
1254
|
}
|
1270
1255
|
|
1271
|
-
var DecrypterAesMode = {
|
1272
|
-
cbc: 0,
|
1273
|
-
ctr: 1
|
1274
|
-
};
|
1275
|
-
|
1276
|
-
function isFullSegmentEncryption(method) {
|
1277
|
-
return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
|
1278
|
-
}
|
1279
|
-
function getAesModeFromFullSegmentMethod(method) {
|
1280
|
-
switch (method) {
|
1281
|
-
case 'AES-128':
|
1282
|
-
case 'AES-256':
|
1283
|
-
return DecrypterAesMode.cbc;
|
1284
|
-
case 'AES-256-CTR':
|
1285
|
-
return DecrypterAesMode.ctr;
|
1286
|
-
default:
|
1287
|
-
throw new Error("invalid full segment method " + method);
|
1288
|
-
}
|
1289
|
-
}
|
1290
|
-
|
1291
1256
|
/** returns `undefined` is `self` is missing, e.g. in node */
|
1292
1257
|
var optionalSelf = typeof self !== 'undefined' ? self : undefined;
|
1293
1258
|
|
@@ -2946,13 +2911,13 @@
|
|
2946
2911
|
this.keyFormatVersions = formatversions;
|
2947
2912
|
this.iv = iv;
|
2948
2913
|
this.encrypted = method ? method !== 'NONE' : false;
|
2949
|
-
this.isCommonEncryption = this.encrypted &&
|
2914
|
+
this.isCommonEncryption = this.encrypted && method !== 'AES-128';
|
2950
2915
|
}
|
2951
2916
|
var _proto = LevelKey.prototype;
|
2952
2917
|
_proto.isSupported = function isSupported() {
|
2953
2918
|
// If it's Segment encryption or No encryption, just select that key system
|
2954
2919
|
if (this.method) {
|
2955
|
-
if (
|
2920
|
+
if (this.method === 'AES-128' || this.method === 'NONE') {
|
2956
2921
|
return true;
|
2957
2922
|
}
|
2958
2923
|
if (this.keyFormat === 'identity') {
|
@@ -2974,13 +2939,14 @@
|
|
2974
2939
|
if (!this.encrypted || !this.uri) {
|
2975
2940
|
return null;
|
2976
2941
|
}
|
2977
|
-
if (
|
2942
|
+
if (this.method === 'AES-128' && this.uri && !this.iv) {
|
2978
2943
|
if (typeof sn !== 'number') {
|
2979
2944
|
// We are fetching decryption data for a initialization segment
|
2980
|
-
// If the segment was encrypted with AES-128
|
2945
|
+
// If the segment was encrypted with AES-128
|
2981
2946
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
2982
|
-
|
2983
|
-
|
2947
|
+
if (this.method === 'AES-128' && !this.iv) {
|
2948
|
+
logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
|
2949
|
+
}
|
2984
2950
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
2985
2951
|
sn = 0;
|
2986
2952
|
}
|
@@ -3274,28 +3240,23 @@
|
|
3274
3240
|
if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
|
3275
3241
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
|
3276
3242
|
}
|
3243
|
+
|
3244
|
+
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3245
|
+
// some browsers will report that fLaC is supported then fail.
|
3246
|
+
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3277
3247
|
var codecsToCheck = {
|
3278
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3279
|
-
// some browsers will report that fLaC is supported then fail.
|
3280
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3281
3248
|
flac: ['flac', 'fLaC', 'FLAC'],
|
3282
|
-
opus: ['opus', 'Opus']
|
3283
|
-
// Replace audio codec info if browser does not support mp4a.40.34,
|
3284
|
-
// and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
|
3285
|
-
'mp4a.40.34': ['mp3']
|
3249
|
+
opus: ['opus', 'Opus']
|
3286
3250
|
}[lowerCaseCodec];
|
3287
3251
|
for (var i = 0; i < codecsToCheck.length; i++) {
|
3288
|
-
var _getMediaSource;
|
3289
3252
|
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
|
3290
3253
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
3291
3254
|
return codecsToCheck[i];
|
3292
|
-
} else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
|
3293
|
-
return '';
|
3294
3255
|
}
|
3295
3256
|
}
|
3296
3257
|
return lowerCaseCodec;
|
3297
3258
|
}
|
3298
|
-
var AUDIO_CODEC_REGEXP = /flac|opus
|
3259
|
+
var AUDIO_CODEC_REGEXP = /flac|opus/i;
|
3299
3260
|
function getCodecCompatibleName(codec, preferManagedMediaSource) {
|
3300
3261
|
if (preferManagedMediaSource === void 0) {
|
3301
3262
|
preferManagedMediaSource = true;
|
@@ -3323,18 +3284,6 @@
|
|
3323
3284
|
}
|
3324
3285
|
return codec;
|
3325
3286
|
}
|
3326
|
-
function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
|
3327
|
-
var MediaSource = getMediaSource(preferManagedMediaSource) || {
|
3328
|
-
isTypeSupported: function isTypeSupported() {
|
3329
|
-
return false;
|
3330
|
-
}
|
3331
|
-
};
|
3332
|
-
return {
|
3333
|
-
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
3334
|
-
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
3335
|
-
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
3336
|
-
};
|
3337
|
-
}
|
3338
3287
|
|
3339
3288
|
var MASTER_PLAYLIST_REGEX = /#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\r\n]*)[\r\n]+/g;
|
3340
3289
|
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
|
@@ -4998,43 +4947,8 @@
|
|
4998
4947
|
this.currentTime = 0;
|
4999
4948
|
this.stallCount = 0;
|
5000
4949
|
this._latency = null;
|
5001
|
-
this.
|
5002
|
-
|
5003
|
-
levelDetails = _this.levelDetails;
|
5004
|
-
if (!media || !levelDetails) {
|
5005
|
-
return;
|
5006
|
-
}
|
5007
|
-
_this.currentTime = media.currentTime;
|
5008
|
-
var latency = _this.computeLatency();
|
5009
|
-
if (latency === null) {
|
5010
|
-
return;
|
5011
|
-
}
|
5012
|
-
_this._latency = latency;
|
5013
|
-
|
5014
|
-
// Adapt playbackRate to meet target latency in low-latency mode
|
5015
|
-
var _this$config = _this.config,
|
5016
|
-
lowLatencyMode = _this$config.lowLatencyMode,
|
5017
|
-
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5018
|
-
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5019
|
-
return;
|
5020
|
-
}
|
5021
|
-
var targetLatency = _this.targetLatency;
|
5022
|
-
if (targetLatency === null) {
|
5023
|
-
return;
|
5024
|
-
}
|
5025
|
-
var distanceFromTarget = latency - targetLatency;
|
5026
|
-
// Only adjust playbackRate when within one target duration of targetLatency
|
5027
|
-
// and more than one second from under-buffering.
|
5028
|
-
// Playback further than one target duration from target can be considered DVR playback.
|
5029
|
-
var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
|
5030
|
-
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5031
|
-
if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
|
5032
|
-
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5033
|
-
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
|
5034
|
-
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5035
|
-
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5036
|
-
media.playbackRate = 1;
|
5037
|
-
}
|
4950
|
+
this.timeupdateHandler = function () {
|
4951
|
+
return _this.timeupdate();
|
5038
4952
|
};
|
5039
4953
|
this.hls = hls;
|
5040
4954
|
this.config = hls.config;
|
@@ -5046,7 +4960,7 @@
|
|
5046
4960
|
this.onMediaDetaching();
|
5047
4961
|
this.levelDetails = null;
|
5048
4962
|
// @ts-ignore
|
5049
|
-
this.hls = null;
|
4963
|
+
this.hls = this.timeupdateHandler = null;
|
5050
4964
|
};
|
5051
4965
|
_proto.registerListeners = function registerListeners() {
|
5052
4966
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -5064,11 +4978,11 @@
|
|
5064
4978
|
};
|
5065
4979
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
5066
4980
|
this.media = data.media;
|
5067
|
-
this.media.addEventListener('timeupdate', this.
|
4981
|
+
this.media.addEventListener('timeupdate', this.timeupdateHandler);
|
5068
4982
|
};
|
5069
4983
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
5070
4984
|
if (this.media) {
|
5071
|
-
this.media.removeEventListener('timeupdate', this.
|
4985
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5072
4986
|
this.media = null;
|
5073
4987
|
}
|
5074
4988
|
};
|
@@ -5081,10 +4995,10 @@
|
|
5081
4995
|
var details = _ref.details;
|
5082
4996
|
this.levelDetails = details;
|
5083
4997
|
if (details.advanced) {
|
5084
|
-
this.
|
4998
|
+
this.timeupdate();
|
5085
4999
|
}
|
5086
5000
|
if (!details.live && this.media) {
|
5087
|
-
this.media.removeEventListener('timeupdate', this.
|
5001
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5088
5002
|
}
|
5089
5003
|
};
|
5090
5004
|
_proto.onError = function onError(event, data) {
|
@@ -5094,7 +5008,45 @@
|
|
5094
5008
|
}
|
5095
5009
|
this.stallCount++;
|
5096
5010
|
if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
|
5097
|
-
|
5011
|
+
logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
|
5012
|
+
}
|
5013
|
+
};
|
5014
|
+
_proto.timeupdate = function timeupdate() {
|
5015
|
+
var media = this.media,
|
5016
|
+
levelDetails = this.levelDetails;
|
5017
|
+
if (!media || !levelDetails) {
|
5018
|
+
return;
|
5019
|
+
}
|
5020
|
+
this.currentTime = media.currentTime;
|
5021
|
+
var latency = this.computeLatency();
|
5022
|
+
if (latency === null) {
|
5023
|
+
return;
|
5024
|
+
}
|
5025
|
+
this._latency = latency;
|
5026
|
+
|
5027
|
+
// Adapt playbackRate to meet target latency in low-latency mode
|
5028
|
+
var _this$config = this.config,
|
5029
|
+
lowLatencyMode = _this$config.lowLatencyMode,
|
5030
|
+
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5031
|
+
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5032
|
+
return;
|
5033
|
+
}
|
5034
|
+
var targetLatency = this.targetLatency;
|
5035
|
+
if (targetLatency === null) {
|
5036
|
+
return;
|
5037
|
+
}
|
5038
|
+
var distanceFromTarget = latency - targetLatency;
|
5039
|
+
// Only adjust playbackRate when within one target duration of targetLatency
|
5040
|
+
// and more than one second from under-buffering.
|
5041
|
+
// Playback further than one target duration from target can be considered DVR playback.
|
5042
|
+
var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
|
5043
|
+
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5044
|
+
if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
|
5045
|
+
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5046
|
+
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
|
5047
|
+
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5048
|
+
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5049
|
+
media.playbackRate = 1;
|
5098
5050
|
}
|
5099
5051
|
};
|
5100
5052
|
_proto.estimateLiveEdge = function estimateLiveEdge() {
|
@@ -6002,17 +5954,19 @@
|
|
6002
5954
|
MoveAllAlternatesMatchingHDCP: 2,
|
6003
5955
|
SwitchToSDR: 4
|
6004
5956
|
}; // Reserved for future use
|
6005
|
-
var ErrorController = /*#__PURE__*/function (
|
6006
|
-
_inheritsLoose(ErrorController, _Logger);
|
5957
|
+
var ErrorController = /*#__PURE__*/function () {
|
6007
5958
|
function ErrorController(hls) {
|
6008
|
-
|
6009
|
-
|
6010
|
-
|
6011
|
-
|
6012
|
-
|
6013
|
-
|
6014
|
-
|
6015
|
-
|
5959
|
+
this.hls = void 0;
|
5960
|
+
this.playlistError = 0;
|
5961
|
+
this.penalizedRenditions = {};
|
5962
|
+
this.log = void 0;
|
5963
|
+
this.warn = void 0;
|
5964
|
+
this.error = void 0;
|
5965
|
+
this.hls = hls;
|
5966
|
+
this.log = logger.log.bind(logger, "[info]:");
|
5967
|
+
this.warn = logger.warn.bind(logger, "[warning]:");
|
5968
|
+
this.error = logger.error.bind(logger, "[error]:");
|
5969
|
+
this.registerListeners();
|
6016
5970
|
}
|
6017
5971
|
var _proto = ErrorController.prototype;
|
6018
5972
|
_proto.registerListeners = function registerListeners() {
|
@@ -6368,19 +6322,19 @@
|
|
6368
6322
|
}
|
6369
6323
|
};
|
6370
6324
|
return ErrorController;
|
6371
|
-
}(
|
6325
|
+
}();
|
6372
6326
|
|
6373
|
-
var BasePlaylistController = /*#__PURE__*/function (
|
6374
|
-
_inheritsLoose(BasePlaylistController, _Logger);
|
6327
|
+
var BasePlaylistController = /*#__PURE__*/function () {
|
6375
6328
|
function BasePlaylistController(hls, logPrefix) {
|
6376
|
-
|
6377
|
-
|
6378
|
-
|
6379
|
-
|
6380
|
-
|
6381
|
-
|
6382
|
-
|
6383
|
-
|
6329
|
+
this.hls = void 0;
|
6330
|
+
this.timer = -1;
|
6331
|
+
this.requestScheduled = -1;
|
6332
|
+
this.canLoad = false;
|
6333
|
+
this.log = void 0;
|
6334
|
+
this.warn = void 0;
|
6335
|
+
this.log = logger.log.bind(logger, logPrefix + ":");
|
6336
|
+
this.warn = logger.warn.bind(logger, logPrefix + ":");
|
6337
|
+
this.hls = hls;
|
6384
6338
|
}
|
6385
6339
|
var _proto = BasePlaylistController.prototype;
|
6386
6340
|
_proto.destroy = function destroy() {
|
@@ -6413,7 +6367,7 @@
|
|
6413
6367
|
try {
|
6414
6368
|
uri = new self.URL(attr.URI, previous.url).href;
|
6415
6369
|
} catch (error) {
|
6416
|
-
|
6370
|
+
logger.warn("Could not construct new URL for Rendition Report: " + error);
|
6417
6371
|
uri = attr.URI || '';
|
6418
6372
|
}
|
6419
6373
|
// Use exact match. Otherwise, the last partial match, if any, will be used
|
@@ -6452,7 +6406,7 @@
|
|
6452
6406
|
return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
|
6453
6407
|
};
|
6454
6408
|
_proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
|
6455
|
-
var
|
6409
|
+
var _this = this;
|
6456
6410
|
var details = data.details,
|
6457
6411
|
stats = data.stats;
|
6458
6412
|
|
@@ -6557,7 +6511,7 @@
|
|
6557
6511
|
// );
|
6558
6512
|
|
6559
6513
|
this.timer = self.setTimeout(function () {
|
6560
|
-
return
|
6514
|
+
return _this.loadPlaylist(deliveryDirectives);
|
6561
6515
|
}, estimatedTimeUntilUpdate);
|
6562
6516
|
} else {
|
6563
6517
|
this.clearTimer();
|
@@ -6573,7 +6527,7 @@
|
|
6573
6527
|
return new HlsUrlParameters(msn, part, skip);
|
6574
6528
|
};
|
6575
6529
|
_proto.checkRetry = function checkRetry(errorEvent) {
|
6576
|
-
var
|
6530
|
+
var _this2 = this;
|
6577
6531
|
var errorDetails = errorEvent.details;
|
6578
6532
|
var isTimeout = isTimeoutError(errorEvent);
|
6579
6533
|
var errorAction = errorEvent.errorAction;
|
@@ -6597,7 +6551,7 @@
|
|
6597
6551
|
var delay = getRetryDelay(retryConfig, retryCount);
|
6598
6552
|
// Schedule level/track reload
|
6599
6553
|
this.timer = self.setTimeout(function () {
|
6600
|
-
return
|
6554
|
+
return _this2.loadPlaylist();
|
6601
6555
|
}, delay);
|
6602
6556
|
this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
|
6603
6557
|
}
|
@@ -6608,7 +6562,7 @@
|
|
6608
6562
|
return retry;
|
6609
6563
|
};
|
6610
6564
|
return BasePlaylistController;
|
6611
|
-
}(
|
6565
|
+
}();
|
6612
6566
|
|
6613
6567
|
/*
|
6614
6568
|
* compute an Exponential Weighted moving average
|
@@ -7210,33 +7164,30 @@
|
|
7210
7164
|
return -1;
|
7211
7165
|
}
|
7212
7166
|
|
7213
|
-
var AbrController = /*#__PURE__*/function (
|
7214
|
-
_inheritsLoose(AbrController, _Logger);
|
7167
|
+
var AbrController = /*#__PURE__*/function () {
|
7215
7168
|
function AbrController(_hls) {
|
7216
|
-
var _this;
|
7217
|
-
|
7218
|
-
|
7219
|
-
|
7220
|
-
|
7221
|
-
|
7222
|
-
|
7223
|
-
|
7224
|
-
|
7225
|
-
|
7226
|
-
|
7227
|
-
|
7228
|
-
|
7229
|
-
|
7230
|
-
_this.bwEstimator = void 0;
|
7169
|
+
var _this = this;
|
7170
|
+
this.hls = void 0;
|
7171
|
+
this.lastLevelLoadSec = 0;
|
7172
|
+
this.lastLoadedFragLevel = -1;
|
7173
|
+
this.firstSelection = -1;
|
7174
|
+
this._nextAutoLevel = -1;
|
7175
|
+
this.nextAutoLevelKey = '';
|
7176
|
+
this.audioTracksByGroup = null;
|
7177
|
+
this.codecTiers = null;
|
7178
|
+
this.timer = -1;
|
7179
|
+
this.fragCurrent = null;
|
7180
|
+
this.partCurrent = null;
|
7181
|
+
this.bitrateTestDelay = 0;
|
7182
|
+
this.bwEstimator = void 0;
|
7231
7183
|
/*
|
7232
7184
|
This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
|
7233
7185
|
quickly enough to prevent underbuffering
|
7234
7186
|
*/
|
7235
|
-
|
7236
|
-
var
|
7237
|
-
|
7238
|
-
|
7239
|
-
hls = _assertThisInitialize.hls;
|
7187
|
+
this._abandonRulesCheck = function () {
|
7188
|
+
var frag = _this.fragCurrent,
|
7189
|
+
part = _this.partCurrent,
|
7190
|
+
hls = _this.hls;
|
7240
7191
|
var autoLevelEnabled = hls.autoLevelEnabled,
|
7241
7192
|
media = hls.media;
|
7242
7193
|
if (!frag || !media) {
|
@@ -7277,7 +7228,7 @@
|
|
7277
7228
|
var bwEstimate = _this.getBwEstimate();
|
7278
7229
|
var levels = hls.levels;
|
7279
7230
|
var level = levels[frag.level];
|
7280
|
-
var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.
|
7231
|
+
var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.averageBitrate / 8));
|
7281
7232
|
var timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
|
7282
7233
|
if (timeStreaming < 1 && loadedFirstByte) {
|
7283
7234
|
timeStreaming = Math.min(timeLoading, stats.loaded * 8 / bwEstimate);
|
@@ -7320,27 +7271,26 @@
|
|
7320
7271
|
// If there has been no loading progress, sample TTFB
|
7321
7272
|
_this.bwEstimator.sampleTTFB(timeLoading);
|
7322
7273
|
}
|
7323
|
-
var nextLoadLevelBitrate = levels[nextLoadLevel].
|
7274
|
+
var nextLoadLevelBitrate = levels[nextLoadLevel].maxBitrate;
|
7324
7275
|
if (_this.getBwEstimate() * _this.hls.config.abrBandWidthUpFactor > nextLoadLevelBitrate) {
|
7325
7276
|
_this.resetEstimator(nextLoadLevelBitrate);
|
7326
7277
|
}
|
7327
7278
|
_this.clearTimer();
|
7328
|
-
|
7279
|
+
logger.warn("[abr] Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + frag.level + " is loading too slowly;\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for down switch fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n TTFB estimate: " + (ttfb | 0) + " ms\n Current BW estimate: " + (isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown') + " bps\n New BW estimate: " + (_this.getBwEstimate() | 0) + " bps\n Switching to level " + nextLoadLevel + " @ " + (nextLoadLevelBitrate | 0) + " bps");
|
7329
7280
|
hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
|
7330
7281
|
frag: frag,
|
7331
7282
|
part: part,
|
7332
7283
|
stats: stats
|
7333
7284
|
});
|
7334
7285
|
};
|
7335
|
-
|
7336
|
-
|
7337
|
-
|
7338
|
-
return _this;
|
7286
|
+
this.hls = _hls;
|
7287
|
+
this.bwEstimator = this.initEstimator();
|
7288
|
+
this.registerListeners();
|
7339
7289
|
}
|
7340
7290
|
var _proto = AbrController.prototype;
|
7341
7291
|
_proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
|
7342
7292
|
if (abrEwmaDefaultEstimate) {
|
7343
|
-
|
7293
|
+
logger.log("setting initial bwe to " + abrEwmaDefaultEstimate);
|
7344
7294
|
this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
|
7345
7295
|
}
|
7346
7296
|
this.firstSelection = -1;
|
@@ -7592,13 +7542,13 @@
|
|
7592
7542
|
// cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
|
7593
7543
|
var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
|
7594
7544
|
maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
|
7595
|
-
|
7545
|
+
logger.info("[abr] bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
|
7596
7546
|
// don't use conservative factor on bitrate test
|
7597
7547
|
bwFactor = bwUpFactor = 1;
|
7598
7548
|
}
|
7599
7549
|
}
|
7600
7550
|
var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
|
7601
|
-
|
7551
|
+
logger.info("[abr] " + (bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
|
7602
7552
|
if (bestLevel > -1) {
|
7603
7553
|
return bestLevel;
|
7604
7554
|
}
|
@@ -7654,7 +7604,7 @@
|
|
7654
7604
|
currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
|
7655
7605
|
currentFrameRate = minFramerate;
|
7656
7606
|
currentBw = Math.max(currentBw, minBitrate);
|
7657
|
-
|
7607
|
+
logger.log("[abr] picked start tier " + JSON.stringify(startTier));
|
7658
7608
|
} else {
|
7659
7609
|
currentCodecSet = level == null ? void 0 : level.codecSet;
|
7660
7610
|
currentVideoRange = level == null ? void 0 : level.videoRange;
|
@@ -7678,11 +7628,11 @@
|
|
7678
7628
|
var levels = _this2.hls.levels;
|
7679
7629
|
var index = levels.indexOf(levelInfo);
|
7680
7630
|
if (decodingInfo.error) {
|
7681
|
-
|
7631
|
+
logger.warn("[abr] MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
|
7682
7632
|
} else if (!decodingInfo.supported) {
|
7683
|
-
|
7633
|
+
logger.warn("[abr] Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
|
7684
7634
|
if (index > -1 && levels.length > 1) {
|
7685
|
-
|
7635
|
+
logger.log("[abr] Removing unsupported level " + index);
|
7686
7636
|
_this2.hls.removeLevel(index);
|
7687
7637
|
}
|
7688
7638
|
}
|
@@ -7729,9 +7679,9 @@
|
|
7729
7679
|
var forcedAutoLevel = _this2.forcedAutoLevel;
|
7730
7680
|
if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
|
7731
7681
|
if (levelsSkipped.length) {
|
7732
|
-
|
7682
|
+
logger.trace("[abr] Skipped level(s) " + levelsSkipped.join(',') + " of " + maxAutoLevel + " max with CODECS and VIDEO-RANGE:\"" + levels[levelsSkipped[0]].codecs + "\" " + levels[levelsSkipped[0]].videoRange + "; not compatible with \"" + level.codecs + "\" " + currentVideoRange);
|
7733
7683
|
}
|
7734
|
-
|
7684
|
+
logger.info("[abr] switch candidate:" + selectionBaseLevel + "->" + i + " adjustedbw(" + Math.round(adjustedbw) + ")-bitrate=" + Math.round(adjustedbw - bitrate) + " ttfb:" + ttfbEstimateSec.toFixed(1) + " avgDuration:" + avgDuration.toFixed(1) + " maxFetchDuration:" + maxFetchDuration.toFixed(1) + " fetchDuration:" + fetchDuration.toFixed(1) + " firstSelection:" + firstSelection + " codecSet:" + currentCodecSet + " videoRange:" + currentVideoRange + " hls.loadLevel:" + loadLevel);
|
7735
7685
|
}
|
7736
7686
|
if (firstSelection) {
|
7737
7687
|
_this2.firstSelection = i;
|
@@ -7765,7 +7715,7 @@
|
|
7765
7715
|
}
|
7766
7716
|
var firstLevel = this.hls.firstLevel;
|
7767
7717
|
var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
|
7768
|
-
|
7718
|
+
logger.warn("[abr] Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
|
7769
7719
|
return clamped;
|
7770
7720
|
}
|
7771
7721
|
}, {
|
@@ -7815,7 +7765,7 @@
|
|
7815
7765
|
}
|
7816
7766
|
}]);
|
7817
7767
|
return AbrController;
|
7818
|
-
}(
|
7768
|
+
}();
|
7819
7769
|
|
7820
7770
|
/**
|
7821
7771
|
* @ignore
|
@@ -7846,17 +7796,13 @@
|
|
7846
7796
|
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
|
7847
7797
|
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
|
7848
7798
|
*/
|
7849
|
-
var TaskLoop = /*#__PURE__*/function (
|
7850
|
-
|
7851
|
-
|
7852
|
-
|
7853
|
-
|
7854
|
-
|
7855
|
-
|
7856
|
-
_this._tickInterval = null;
|
7857
|
-
_this._tickCallCount = 0;
|
7858
|
-
_this._boundTick = _this.tick.bind(_assertThisInitialized(_this));
|
7859
|
-
return _this;
|
7799
|
+
var TaskLoop = /*#__PURE__*/function () {
|
7800
|
+
function TaskLoop() {
|
7801
|
+
this._boundTick = void 0;
|
7802
|
+
this._tickTimer = null;
|
7803
|
+
this._tickInterval = null;
|
7804
|
+
this._tickCallCount = 0;
|
7805
|
+
this._boundTick = this.tick.bind(this);
|
7860
7806
|
}
|
7861
7807
|
var _proto = TaskLoop.prototype;
|
7862
7808
|
_proto.destroy = function destroy() {
|
@@ -7942,7 +7888,7 @@
|
|
7942
7888
|
*/;
|
7943
7889
|
_proto.doTick = function doTick() {};
|
7944
7890
|
return TaskLoop;
|
7945
|
-
}(
|
7891
|
+
}();
|
7946
7892
|
|
7947
7893
|
var FragmentState = {
|
7948
7894
|
NOT_LOADED: "NOT_LOADED",
|
@@ -8961,8 +8907,8 @@
|
|
8961
8907
|
var _frag$decryptdata;
|
8962
8908
|
var byteRangeStart = start;
|
8963
8909
|
var byteRangeEnd = end;
|
8964
|
-
if (frag.sn === 'initSegment' &&
|
8965
|
-
// MAP segment encrypted with method 'AES-128'
|
8910
|
+
if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
|
8911
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
8966
8912
|
// has the unencrypted size specified in the range.
|
8967
8913
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
8968
8914
|
var fragmentLen = end - start;
|
@@ -8995,9 +8941,6 @@
|
|
8995
8941
|
(part ? part : frag).stats.aborted = true;
|
8996
8942
|
return new LoadError(errorData);
|
8997
8943
|
}
|
8998
|
-
function isMethodFullSegmentAesCbc(method) {
|
8999
|
-
return method === 'AES-128' || method === 'AES-256';
|
9000
|
-
}
|
9001
8944
|
var LoadError = /*#__PURE__*/function (_Error) {
|
9002
8945
|
_inheritsLoose(LoadError, _Error);
|
9003
8946
|
function LoadError(data) {
|
@@ -9011,65 +8954,37 @@
|
|
9011
8954
|
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
9012
8955
|
|
9013
8956
|
var AESCrypto = /*#__PURE__*/function () {
|
9014
|
-
function AESCrypto(subtle, iv
|
8957
|
+
function AESCrypto(subtle, iv) {
|
9015
8958
|
this.subtle = void 0;
|
9016
8959
|
this.aesIV = void 0;
|
9017
|
-
this.aesMode = void 0;
|
9018
8960
|
this.subtle = subtle;
|
9019
8961
|
this.aesIV = iv;
|
9020
|
-
this.aesMode = aesMode;
|
9021
8962
|
}
|
9022
8963
|
var _proto = AESCrypto.prototype;
|
9023
8964
|
_proto.decrypt = function decrypt(data, key) {
|
9024
|
-
|
9025
|
-
|
9026
|
-
|
9027
|
-
|
9028
|
-
iv: this.aesIV
|
9029
|
-
}, key, data);
|
9030
|
-
case DecrypterAesMode.ctr:
|
9031
|
-
return this.subtle.decrypt({
|
9032
|
-
name: 'AES-CTR',
|
9033
|
-
counter: this.aesIV,
|
9034
|
-
length: 64
|
9035
|
-
},
|
9036
|
-
//64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
|
9037
|
-
key, data);
|
9038
|
-
default:
|
9039
|
-
throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
|
9040
|
-
}
|
8965
|
+
return this.subtle.decrypt({
|
8966
|
+
name: 'AES-CBC',
|
8967
|
+
iv: this.aesIV
|
8968
|
+
}, key, data);
|
9041
8969
|
};
|
9042
8970
|
return AESCrypto;
|
9043
8971
|
}();
|
9044
8972
|
|
9045
8973
|
var FastAESKey = /*#__PURE__*/function () {
|
9046
|
-
function FastAESKey(subtle, key
|
8974
|
+
function FastAESKey(subtle, key) {
|
9047
8975
|
this.subtle = void 0;
|
9048
8976
|
this.key = void 0;
|
9049
|
-
this.aesMode = void 0;
|
9050
8977
|
this.subtle = subtle;
|
9051
8978
|
this.key = key;
|
9052
|
-
this.aesMode = aesMode;
|
9053
8979
|
}
|
9054
8980
|
var _proto = FastAESKey.prototype;
|
9055
8981
|
_proto.expandKey = function expandKey() {
|
9056
|
-
var subtleAlgoName = getSubtleAlgoName(this.aesMode);
|
9057
8982
|
return this.subtle.importKey('raw', this.key, {
|
9058
|
-
name:
|
8983
|
+
name: 'AES-CBC'
|
9059
8984
|
}, false, ['encrypt', 'decrypt']);
|
9060
8985
|
};
|
9061
8986
|
return FastAESKey;
|
9062
8987
|
}();
|
9063
|
-
function getSubtleAlgoName(aesMode) {
|
9064
|
-
switch (aesMode) {
|
9065
|
-
case DecrypterAesMode.cbc:
|
9066
|
-
return 'AES-CBC';
|
9067
|
-
case DecrypterAesMode.ctr:
|
9068
|
-
return 'AES-CTR';
|
9069
|
-
default:
|
9070
|
-
throw new Error("[FastAESKey] invalid aes mode " + aesMode);
|
9071
|
-
}
|
9072
|
-
}
|
9073
8988
|
|
9074
8989
|
// PKCS7
|
9075
8990
|
function removePadding(array) {
|
@@ -9322,8 +9237,7 @@
|
|
9322
9237
|
this.currentIV = null;
|
9323
9238
|
this.currentResult = null;
|
9324
9239
|
this.useSoftware = void 0;
|
9325
|
-
this.
|
9326
|
-
this.enableSoftwareAES = config.enableSoftwareAES;
|
9240
|
+
this.useSoftware = config.enableSoftwareAES;
|
9327
9241
|
this.removePKCS7Padding = removePKCS7Padding;
|
9328
9242
|
// built in decryptor expects PKCS7 padding
|
9329
9243
|
if (removePKCS7Padding) {
|
@@ -9336,7 +9250,9 @@
|
|
9336
9250
|
/* no-op */
|
9337
9251
|
}
|
9338
9252
|
}
|
9339
|
-
|
9253
|
+
if (this.subtle === null) {
|
9254
|
+
this.useSoftware = true;
|
9255
|
+
}
|
9340
9256
|
}
|
9341
9257
|
var _proto = Decrypter.prototype;
|
9342
9258
|
_proto.destroy = function destroy() {
|
@@ -9373,11 +9289,11 @@
|
|
9373
9289
|
this.softwareDecrypter = null;
|
9374
9290
|
}
|
9375
9291
|
};
|
9376
|
-
_proto.decrypt = function decrypt(data, key, iv
|
9292
|
+
_proto.decrypt = function decrypt(data, key, iv) {
|
9377
9293
|
var _this = this;
|
9378
9294
|
if (this.useSoftware) {
|
9379
9295
|
return new Promise(function (resolve, reject) {
|
9380
|
-
_this.softwareDecrypt(new Uint8Array(data), key, iv
|
9296
|
+
_this.softwareDecrypt(new Uint8Array(data), key, iv);
|
9381
9297
|
var decryptResult = _this.flush();
|
9382
9298
|
if (decryptResult) {
|
9383
9299
|
resolve(decryptResult.buffer);
|
@@ -9386,20 +9302,16 @@
|
|
9386
9302
|
}
|
9387
9303
|
});
|
9388
9304
|
}
|
9389
|
-
return this.webCryptoDecrypt(new Uint8Array(data), key, iv
|
9305
|
+
return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
|
9390
9306
|
}
|
9391
9307
|
|
9392
9308
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
9393
9309
|
// data is handled in the flush() call
|
9394
9310
|
;
|
9395
|
-
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv
|
9311
|
+
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
|
9396
9312
|
var currentIV = this.currentIV,
|
9397
9313
|
currentResult = this.currentResult,
|
9398
9314
|
remainderData = this.remainderData;
|
9399
|
-
if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
|
9400
|
-
logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
|
9401
|
-
return null;
|
9402
|
-
}
|
9403
9315
|
this.logOnce('JS AES decrypt');
|
9404
9316
|
// The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
|
9405
9317
|
// This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
|
@@ -9432,12 +9344,12 @@
|
|
9432
9344
|
}
|
9433
9345
|
return result;
|
9434
9346
|
};
|
9435
|
-
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv
|
9347
|
+
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
|
9436
9348
|
var _this2 = this;
|
9437
9349
|
var subtle = this.subtle;
|
9438
9350
|
if (this.key !== key || !this.fastAesKey) {
|
9439
9351
|
this.key = key;
|
9440
|
-
this.fastAesKey = new FastAESKey(subtle, key
|
9352
|
+
this.fastAesKey = new FastAESKey(subtle, key);
|
9441
9353
|
}
|
9442
9354
|
return this.fastAesKey.expandKey().then(function (aesKey) {
|
9443
9355
|
// decrypt using web crypto
|
@@ -9445,25 +9357,22 @@
|
|
9445
9357
|
return Promise.reject(new Error('web crypto not initialized'));
|
9446
9358
|
}
|
9447
9359
|
_this2.logOnce('WebCrypto AES decrypt');
|
9448
|
-
var crypto = new AESCrypto(subtle, new Uint8Array(iv)
|
9360
|
+
var crypto = new AESCrypto(subtle, new Uint8Array(iv));
|
9449
9361
|
return crypto.decrypt(data.buffer, aesKey);
|
9450
9362
|
}).catch(function (err) {
|
9451
9363
|
logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
|
9452
|
-
return _this2.onWebCryptoError(data, key, iv
|
9364
|
+
return _this2.onWebCryptoError(data, key, iv);
|
9453
9365
|
});
|
9454
9366
|
};
|
9455
|
-
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv
|
9456
|
-
|
9457
|
-
|
9458
|
-
|
9459
|
-
|
9460
|
-
|
9461
|
-
|
9462
|
-
if (decryptResult) {
|
9463
|
-
return decryptResult.buffer;
|
9464
|
-
}
|
9367
|
+
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
|
9368
|
+
this.useSoftware = true;
|
9369
|
+
this.logEnabled = true;
|
9370
|
+
this.softwareDecrypt(data, key, iv);
|
9371
|
+
var decryptResult = this.flush();
|
9372
|
+
if (decryptResult) {
|
9373
|
+
return decryptResult.buffer;
|
9465
9374
|
}
|
9466
|
-
throw new Error('WebCrypto
|
9375
|
+
throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
|
9467
9376
|
};
|
9468
9377
|
_proto.getValidChunk = function getValidChunk(data) {
|
9469
9378
|
var currentChunk = data;
|
@@ -9517,7 +9426,7 @@
|
|
9517
9426
|
_inheritsLoose(BaseStreamController, _TaskLoop);
|
9518
9427
|
function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
|
9519
9428
|
var _this;
|
9520
|
-
_this = _TaskLoop.call(this
|
9429
|
+
_this = _TaskLoop.call(this) || this;
|
9521
9430
|
_this.hls = void 0;
|
9522
9431
|
_this.fragPrevious = null;
|
9523
9432
|
_this.fragCurrent = null;
|
@@ -9542,81 +9451,25 @@
|
|
9542
9451
|
_this.startFragRequested = false;
|
9543
9452
|
_this.decrypter = void 0;
|
9544
9453
|
_this.initPTS = [];
|
9545
|
-
_this.
|
9546
|
-
|
9547
|
-
|
9548
|
-
|
9549
|
-
|
9550
|
-
mediaBuffer = _assertThisInitialize.mediaBuffer,
|
9551
|
-
state = _assertThisInitialize.state;
|
9552
|
-
var currentTime = media ? media.currentTime : 0;
|
9553
|
-
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9554
|
-
_this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9555
|
-
if (_this.state === State.ENDED) {
|
9556
|
-
_this.resetLoadingState();
|
9557
|
-
} else if (fragCurrent) {
|
9558
|
-
// Seeking while frag load is in progress
|
9559
|
-
var tolerance = config.maxFragLookUpTolerance;
|
9560
|
-
var fragStartOffset = fragCurrent.start - tolerance;
|
9561
|
-
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9562
|
-
// if seeking out of buffered range or into new one
|
9563
|
-
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9564
|
-
var pastFragment = currentTime > fragEndOffset;
|
9565
|
-
// if the seek position is outside the current fragment range
|
9566
|
-
if (currentTime < fragStartOffset || pastFragment) {
|
9567
|
-
if (pastFragment && fragCurrent.loader) {
|
9568
|
-
_this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9569
|
-
fragCurrent.abortRequests();
|
9570
|
-
_this.resetLoadingState();
|
9571
|
-
}
|
9572
|
-
_this.fragPrevious = null;
|
9573
|
-
}
|
9574
|
-
}
|
9575
|
-
}
|
9576
|
-
if (media) {
|
9577
|
-
// Remove gap fragments
|
9578
|
-
_this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
|
9579
|
-
_this.lastCurrentTime = currentTime;
|
9580
|
-
}
|
9581
|
-
|
9582
|
-
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9583
|
-
if (!_this.loadedmetadata && !bufferInfo.len) {
|
9584
|
-
_this.nextLoadPosition = _this.startPosition = currentTime;
|
9585
|
-
}
|
9586
|
-
|
9587
|
-
// Async tick to speed up processing
|
9588
|
-
_this.tickImmediate();
|
9589
|
-
};
|
9590
|
-
_this.onMediaEnded = function () {
|
9591
|
-
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9592
|
-
_this.startPosition = _this.lastCurrentTime = 0;
|
9593
|
-
};
|
9454
|
+
_this.onvseeking = null;
|
9455
|
+
_this.onvended = null;
|
9456
|
+
_this.logPrefix = '';
|
9457
|
+
_this.log = void 0;
|
9458
|
+
_this.warn = void 0;
|
9594
9459
|
_this.playlistType = playlistType;
|
9460
|
+
_this.logPrefix = logPrefix;
|
9461
|
+
_this.log = logger.log.bind(logger, logPrefix + ":");
|
9462
|
+
_this.warn = logger.warn.bind(logger, logPrefix + ":");
|
9595
9463
|
_this.hls = hls;
|
9596
9464
|
_this.fragmentLoader = new FragmentLoader(hls.config);
|
9597
9465
|
_this.keyLoader = keyLoader;
|
9598
9466
|
_this.fragmentTracker = fragmentTracker;
|
9599
9467
|
_this.config = hls.config;
|
9600
9468
|
_this.decrypter = new Decrypter(hls.config);
|
9469
|
+
hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
|
9601
9470
|
return _this;
|
9602
9471
|
}
|
9603
9472
|
var _proto = BaseStreamController.prototype;
|
9604
|
-
_proto.registerListeners = function registerListeners() {
|
9605
|
-
var hls = this.hls;
|
9606
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9607
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9608
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9609
|
-
hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9610
|
-
hls.on(Events.ERROR, this.onError, this);
|
9611
|
-
};
|
9612
|
-
_proto.unregisterListeners = function unregisterListeners() {
|
9613
|
-
var hls = this.hls;
|
9614
|
-
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9615
|
-
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9616
|
-
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9617
|
-
hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9618
|
-
hls.off(Events.ERROR, this.onError, this);
|
9619
|
-
};
|
9620
9473
|
_proto.doTick = function doTick() {
|
9621
9474
|
this.onTickEnd();
|
9622
9475
|
};
|
@@ -9670,8 +9523,10 @@
|
|
9670
9523
|
};
|
9671
9524
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
9672
9525
|
var media = this.media = this.mediaBuffer = data.media;
|
9673
|
-
|
9674
|
-
|
9526
|
+
this.onvseeking = this.onMediaSeeking.bind(this);
|
9527
|
+
this.onvended = this.onMediaEnded.bind(this);
|
9528
|
+
media.addEventListener('seeking', this.onvseeking);
|
9529
|
+
media.addEventListener('ended', this.onvended);
|
9675
9530
|
var config = this.config;
|
9676
9531
|
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
|
9677
9532
|
this.startLoad(config.startPosition);
|
@@ -9685,9 +9540,10 @@
|
|
9685
9540
|
}
|
9686
9541
|
|
9687
9542
|
// remove video listeners
|
9688
|
-
if (media) {
|
9689
|
-
media.removeEventListener('seeking', this.
|
9690
|
-
media.removeEventListener('ended', this.
|
9543
|
+
if (media && this.onvseeking && this.onvended) {
|
9544
|
+
media.removeEventListener('seeking', this.onvseeking);
|
9545
|
+
media.removeEventListener('ended', this.onvended);
|
9546
|
+
this.onvseeking = this.onvended = null;
|
9691
9547
|
}
|
9692
9548
|
if (this.keyLoader) {
|
9693
9549
|
this.keyLoader.detach();
|
@@ -9697,8 +9553,54 @@
|
|
9697
9553
|
this.fragmentTracker.removeAllFragments();
|
9698
9554
|
this.stopLoad();
|
9699
9555
|
};
|
9700
|
-
_proto.
|
9701
|
-
|
9556
|
+
_proto.onMediaSeeking = function onMediaSeeking() {
|
9557
|
+
var config = this.config,
|
9558
|
+
fragCurrent = this.fragCurrent,
|
9559
|
+
media = this.media,
|
9560
|
+
mediaBuffer = this.mediaBuffer,
|
9561
|
+
state = this.state;
|
9562
|
+
var currentTime = media ? media.currentTime : 0;
|
9563
|
+
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9564
|
+
this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9565
|
+
if (this.state === State.ENDED) {
|
9566
|
+
this.resetLoadingState();
|
9567
|
+
} else if (fragCurrent) {
|
9568
|
+
// Seeking while frag load is in progress
|
9569
|
+
var tolerance = config.maxFragLookUpTolerance;
|
9570
|
+
var fragStartOffset = fragCurrent.start - tolerance;
|
9571
|
+
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9572
|
+
// if seeking out of buffered range or into new one
|
9573
|
+
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9574
|
+
var pastFragment = currentTime > fragEndOffset;
|
9575
|
+
// if the seek position is outside the current fragment range
|
9576
|
+
if (currentTime < fragStartOffset || pastFragment) {
|
9577
|
+
if (pastFragment && fragCurrent.loader) {
|
9578
|
+
this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9579
|
+
fragCurrent.abortRequests();
|
9580
|
+
this.resetLoadingState();
|
9581
|
+
}
|
9582
|
+
this.fragPrevious = null;
|
9583
|
+
}
|
9584
|
+
}
|
9585
|
+
}
|
9586
|
+
if (media) {
|
9587
|
+
// Remove gap fragments
|
9588
|
+
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
9589
|
+
this.lastCurrentTime = currentTime;
|
9590
|
+
}
|
9591
|
+
|
9592
|
+
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9593
|
+
if (!this.loadedmetadata && !bufferInfo.len) {
|
9594
|
+
this.nextLoadPosition = this.startPosition = currentTime;
|
9595
|
+
}
|
9596
|
+
|
9597
|
+
// Async tick to speed up processing
|
9598
|
+
this.tickImmediate();
|
9599
|
+
};
|
9600
|
+
_proto.onMediaEnded = function onMediaEnded() {
|
9601
|
+
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9602
|
+
this.startPosition = this.lastCurrentTime = 0;
|
9603
|
+
};
|
9702
9604
|
_proto.onManifestLoaded = function onManifestLoaded(event, data) {
|
9703
9605
|
this.startTimeOffset = data.startTimeOffset;
|
9704
9606
|
this.initPTS = [];
|
@@ -9708,7 +9610,7 @@
|
|
9708
9610
|
this.stopLoad();
|
9709
9611
|
_TaskLoop.prototype.onHandlerDestroying.call(this);
|
9710
9612
|
// @ts-ignore
|
9711
|
-
this.hls =
|
9613
|
+
this.hls = null;
|
9712
9614
|
};
|
9713
9615
|
_proto.onHandlerDestroyed = function onHandlerDestroyed() {
|
9714
9616
|
this.state = State.STOPPED;
|
@@ -9838,10 +9740,10 @@
|
|
9838
9740
|
var decryptData = frag.decryptdata;
|
9839
9741
|
|
9840
9742
|
// check to see if the payload needs to be decrypted
|
9841
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
9743
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
9842
9744
|
var startTime = self.performance.now();
|
9843
9745
|
// decrypt init segment data
|
9844
|
-
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
9746
|
+
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
9845
9747
|
hls.trigger(Events.ERROR, {
|
9846
9748
|
type: ErrorTypes.MEDIA_ERROR,
|
9847
9749
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -9954,7 +9856,7 @@
|
|
9954
9856
|
}
|
9955
9857
|
var keyLoadingPromise = null;
|
9956
9858
|
if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
|
9957
|
-
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.
|
9859
|
+
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level);
|
9958
9860
|
this.state = State.KEY_LOADING;
|
9959
9861
|
this.fragCurrent = frag;
|
9960
9862
|
keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
|
@@ -9985,7 +9887,7 @@
|
|
9985
9887
|
var partIndex = this.getNextPart(partList, frag, targetBufferTime);
|
9986
9888
|
if (partIndex > -1) {
|
9987
9889
|
var part = partList[partIndex];
|
9988
|
-
this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.
|
9890
|
+
this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
|
9989
9891
|
this.nextLoadPosition = part.start + part.duration;
|
9990
9892
|
this.state = State.FRAG_LOADING;
|
9991
9893
|
var _result;
|
@@ -10018,7 +9920,7 @@
|
|
10018
9920
|
}
|
10019
9921
|
}
|
10020
9922
|
}
|
10021
|
-
this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.
|
9923
|
+
this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
|
10022
9924
|
// Don't update nextLoadPosition for fragments which are not buffered
|
10023
9925
|
if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
|
10024
9926
|
this.nextLoadPosition = frag.start + frag.duration;
|
@@ -10579,7 +10481,7 @@
|
|
10579
10481
|
errorAction.resolved = true;
|
10580
10482
|
}
|
10581
10483
|
} else {
|
10582
|
-
|
10484
|
+
logger.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
|
10583
10485
|
return;
|
10584
10486
|
}
|
10585
10487
|
} else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
|
@@ -10979,7 +10881,6 @@
|
|
10979
10881
|
*/
|
10980
10882
|
function getAudioConfig(observer, data, offset, audioCodec) {
|
10981
10883
|
var adtsObjectType;
|
10982
|
-
var originalAdtsObjectType;
|
10983
10884
|
var adtsExtensionSamplingIndex;
|
10984
10885
|
var adtsChannelConfig;
|
10985
10886
|
var config;
|
@@ -10987,7 +10888,7 @@
|
|
10987
10888
|
var manifestCodec = audioCodec;
|
10988
10889
|
var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
|
10989
10890
|
// byte 2
|
10990
|
-
adtsObjectType =
|
10891
|
+
adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
10991
10892
|
var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
|
10992
10893
|
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
|
10993
10894
|
var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
|
@@ -11004,8 +10905,8 @@
|
|
11004
10905
|
// byte 3
|
11005
10906
|
adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
|
11006
10907
|
logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
|
11007
|
-
//
|
11008
|
-
if (/firefox
|
10908
|
+
// firefox: freq less than 24kHz = AAC SBR (HE-AAC)
|
10909
|
+
if (/firefox/i.test(userAgent)) {
|
11009
10910
|
if (adtsSamplingIndex >= 6) {
|
11010
10911
|
adtsObjectType = 5;
|
11011
10912
|
config = new Array(4);
|
@@ -11099,7 +11000,6 @@
|
|
11099
11000
|
samplerate: adtsSamplingRates[adtsSamplingIndex],
|
11100
11001
|
channelCount: adtsChannelConfig,
|
11101
11002
|
codec: 'mp4a.40.' + adtsObjectType,
|
11102
|
-
parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
|
11103
11003
|
manifestCodec: manifestCodec
|
11104
11004
|
};
|
11105
11005
|
}
|
@@ -11154,8 +11054,7 @@
|
|
11154
11054
|
track.channelCount = config.channelCount;
|
11155
11055
|
track.codec = config.codec;
|
11156
11056
|
track.manifestCodec = config.manifestCodec;
|
11157
|
-
track.
|
11158
|
-
logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11057
|
+
logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11159
11058
|
}
|
11160
11059
|
}
|
11161
11060
|
function getFrameDuration(samplerate) {
|
@@ -12360,7 +12259,7 @@
|
|
12360
12259
|
}
|
12361
12260
|
var _proto = SampleAesDecrypter.prototype;
|
12362
12261
|
_proto.decryptBuffer = function decryptBuffer(encryptedData) {
|
12363
|
-
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer
|
12262
|
+
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
|
12364
12263
|
}
|
12365
12264
|
|
12366
12265
|
// AAC - encrypt all full 16 bytes blocks starting from offset 16
|
@@ -14639,7 +14538,7 @@
|
|
14639
14538
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
14640
14539
|
for (var j = 0; j < missing; j++) {
|
14641
14540
|
var newStamp = Math.max(nextPts, 0);
|
14642
|
-
var fillFrame = AAC.getSilentFrame(track.
|
14541
|
+
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
14643
14542
|
if (!fillFrame) {
|
14644
14543
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
14645
14544
|
fillFrame = sample.unit.subarray();
|
@@ -14767,7 +14666,7 @@
|
|
14767
14666
|
// samples count of this segment's duration
|
14768
14667
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
14769
14668
|
// silent frame
|
14770
|
-
var silentFrame = AAC.getSilentFrame(track.
|
14669
|
+
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
14771
14670
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
14772
14671
|
// Can't remux if we can't generate a silent frame...
|
14773
14672
|
if (!silentFrame) {
|
@@ -15157,15 +15056,13 @@
|
|
15157
15056
|
duration = transmuxConfig.duration,
|
15158
15057
|
initSegmentData = transmuxConfig.initSegmentData;
|
15159
15058
|
var keyData = getEncryptionType(uintData, decryptdata);
|
15160
|
-
if (keyData &&
|
15059
|
+
if (keyData && keyData.method === 'AES-128') {
|
15161
15060
|
var decrypter = this.getDecrypter();
|
15162
|
-
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
15163
|
-
|
15164
15061
|
// Software decryption is synchronous; webCrypto is not
|
15165
15062
|
if (decrypter.isSync()) {
|
15166
15063
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
15167
15064
|
// data is handled in the flush() call
|
15168
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15065
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
15169
15066
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
15170
15067
|
var loadingParts = chunkMeta.part > -1;
|
15171
15068
|
if (loadingParts) {
|
@@ -15177,7 +15074,7 @@
|
|
15177
15074
|
}
|
15178
15075
|
uintData = new Uint8Array(decryptedData);
|
15179
15076
|
} else {
|
15180
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15077
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
15181
15078
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
15182
15079
|
// the decrypted data has been transmuxed
|
15183
15080
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -15798,7 +15695,7 @@
|
|
15798
15695
|
observer.on(Events.ERROR, forwardMessage);
|
15799
15696
|
|
15800
15697
|
// forward logger events to main thread
|
15801
|
-
var forwardWorkerLogs = function forwardWorkerLogs(
|
15698
|
+
var forwardWorkerLogs = function forwardWorkerLogs() {
|
15802
15699
|
var _loop = function _loop(logFn) {
|
15803
15700
|
var func = function func(message) {
|
15804
15701
|
forwardMessage('workerLog', {
|
@@ -15819,8 +15716,8 @@
|
|
15819
15716
|
{
|
15820
15717
|
var config = JSON.parse(data.config);
|
15821
15718
|
self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
|
15822
|
-
|
15823
|
-
forwardWorkerLogs(
|
15719
|
+
enableLogs(config.debug, data.id);
|
15720
|
+
forwardWorkerLogs();
|
15824
15721
|
forwardMessage('init', null);
|
15825
15722
|
break;
|
15826
15723
|
}
|
@@ -15994,7 +15891,16 @@
|
|
15994
15891
|
this.observer = new EventEmitter();
|
15995
15892
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
15996
15893
|
this.observer.on(Events.ERROR, forwardMessage);
|
15997
|
-
var
|
15894
|
+
var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
|
15895
|
+
isTypeSupported: function isTypeSupported() {
|
15896
|
+
return false;
|
15897
|
+
}
|
15898
|
+
};
|
15899
|
+
var m2tsTypeSupported = {
|
15900
|
+
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
15901
|
+
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
15902
|
+
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
15903
|
+
};
|
15998
15904
|
|
15999
15905
|
// navigator.vendor is not always available in Web Worker
|
16000
15906
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -16278,7 +16184,7 @@
|
|
16278
16184
|
_inheritsLoose(AudioStreamController, _BaseStreamController);
|
16279
16185
|
function AudioStreamController(hls, fragmentTracker, keyLoader) {
|
16280
16186
|
var _this;
|
16281
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
|
16187
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]', PlaylistLevelType.AUDIO) || this;
|
16282
16188
|
_this.videoBuffer = null;
|
16283
16189
|
_this.videoTrackCC = -1;
|
16284
16190
|
_this.waitingVideoCC = -1;
|
@@ -16290,24 +16196,27 @@
|
|
16290
16196
|
_this.flushing = false;
|
16291
16197
|
_this.bufferFlushed = false;
|
16292
16198
|
_this.cachedTrackLoadedData = null;
|
16293
|
-
_this.
|
16199
|
+
_this._registerListeners();
|
16294
16200
|
return _this;
|
16295
16201
|
}
|
16296
16202
|
var _proto = AudioStreamController.prototype;
|
16297
16203
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
16298
|
-
this.
|
16204
|
+
this._unregisterListeners();
|
16299
16205
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
16300
16206
|
this.mainDetails = null;
|
16301
16207
|
this.bufferedTrack = null;
|
16302
16208
|
this.switchingTrack = null;
|
16303
16209
|
};
|
16304
|
-
_proto.
|
16305
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
16210
|
+
_proto._registerListeners = function _registerListeners() {
|
16306
16211
|
var hls = this.hls;
|
16212
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16213
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16214
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
16307
16215
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16308
16216
|
hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16309
16217
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16310
16218
|
hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16219
|
+
hls.on(Events.ERROR, this.onError, this);
|
16311
16220
|
hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
|
16312
16221
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16313
16222
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -16315,16 +16224,16 @@
|
|
16315
16224
|
hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
|
16316
16225
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
16317
16226
|
};
|
16318
|
-
_proto.
|
16227
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
16319
16228
|
var hls = this.hls;
|
16320
|
-
|
16321
|
-
|
16322
|
-
|
16323
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
16229
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16230
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16231
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
16324
16232
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16325
16233
|
hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16326
16234
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16327
16235
|
hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16236
|
+
hls.off(Events.ERROR, this.onError, this);
|
16328
16237
|
hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
|
16329
16238
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16330
16239
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -17017,7 +16926,7 @@
|
|
17017
16926
|
_inheritsLoose(AudioTrackController, _BasePlaylistControll);
|
17018
16927
|
function AudioTrackController(hls) {
|
17019
16928
|
var _this;
|
17020
|
-
_this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
|
16929
|
+
_this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this;
|
17021
16930
|
_this.tracks = [];
|
17022
16931
|
_this.groupIds = null;
|
17023
16932
|
_this.tracksInGroup = [];
|
@@ -17346,23 +17255,26 @@
|
|
17346
17255
|
_inheritsLoose(SubtitleStreamController, _BaseStreamController);
|
17347
17256
|
function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
|
17348
17257
|
var _this;
|
17349
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
|
17258
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]', PlaylistLevelType.SUBTITLE) || this;
|
17350
17259
|
_this.currentTrackId = -1;
|
17351
17260
|
_this.tracksBuffered = [];
|
17352
17261
|
_this.mainDetails = null;
|
17353
|
-
_this.
|
17262
|
+
_this._registerListeners();
|
17354
17263
|
return _this;
|
17355
17264
|
}
|
17356
17265
|
var _proto = SubtitleStreamController.prototype;
|
17357
17266
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
17358
|
-
this.
|
17267
|
+
this._unregisterListeners();
|
17359
17268
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
17360
17269
|
this.mainDetails = null;
|
17361
17270
|
};
|
17362
|
-
_proto.
|
17363
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
17271
|
+
_proto._registerListeners = function _registerListeners() {
|
17364
17272
|
var hls = this.hls;
|
17273
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17274
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17275
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17365
17276
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17277
|
+
hls.on(Events.ERROR, this.onError, this);
|
17366
17278
|
hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17367
17279
|
hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17368
17280
|
hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17370,10 +17282,13 @@
|
|
17370
17282
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
17371
17283
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
17372
17284
|
};
|
17373
|
-
_proto.
|
17374
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
17285
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
17375
17286
|
var hls = this.hls;
|
17287
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17288
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17289
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17376
17290
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17291
|
+
hls.off(Events.ERROR, this.onError, this);
|
17377
17292
|
hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17378
17293
|
hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17379
17294
|
hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17596,10 +17511,10 @@
|
|
17596
17511
|
return;
|
17597
17512
|
}
|
17598
17513
|
// check to see if the payload needs to be decrypted
|
17599
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
17514
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
17600
17515
|
var startTime = performance.now();
|
17601
17516
|
// decrypt the subtitles
|
17602
|
-
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
17517
|
+
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
17603
17518
|
hls.trigger(Events.ERROR, {
|
17604
17519
|
type: ErrorTypes.MEDIA_ERROR,
|
17605
17520
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -17731,7 +17646,7 @@
|
|
17731
17646
|
_inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
|
17732
17647
|
function SubtitleTrackController(hls) {
|
17733
17648
|
var _this;
|
17734
|
-
_this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
|
17649
|
+
_this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this;
|
17735
17650
|
_this.media = null;
|
17736
17651
|
_this.tracks = [];
|
17737
17652
|
_this.groupIds = null;
|
@@ -17740,12 +17655,12 @@
|
|
17740
17655
|
_this.currentTrack = null;
|
17741
17656
|
_this.selectDefaultTrack = true;
|
17742
17657
|
_this.queuedDefaultTrack = -1;
|
17743
|
-
_this.useTextTrackPolling = false;
|
17744
|
-
_this.subtitlePollingInterval = -1;
|
17745
|
-
_this._subtitleDisplay = true;
|
17746
17658
|
_this.asyncPollTrackChange = function () {
|
17747
17659
|
return _this.pollTrackChange(0);
|
17748
17660
|
};
|
17661
|
+
_this.useTextTrackPolling = false;
|
17662
|
+
_this.subtitlePollingInterval = -1;
|
17663
|
+
_this._subtitleDisplay = true;
|
17749
17664
|
_this.onTextTracksChanged = function () {
|
17750
17665
|
if (!_this.useTextTrackPolling) {
|
17751
17666
|
self.clearInterval(_this.subtitlePollingInterval);
|
@@ -17781,7 +17696,6 @@
|
|
17781
17696
|
this.tracks.length = 0;
|
17782
17697
|
this.tracksInGroup.length = 0;
|
17783
17698
|
this.currentTrack = null;
|
17784
|
-
// @ts-ignore
|
17785
17699
|
this.onTextTracksChanged = this.asyncPollTrackChange = null;
|
17786
17700
|
_BasePlaylistControll.prototype.destroy.call(this);
|
17787
17701
|
};
|
@@ -18255,57 +18169,57 @@
|
|
18255
18169
|
}();
|
18256
18170
|
|
18257
18171
|
var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
|
18258
|
-
var BufferController = /*#__PURE__*/function (
|
18259
|
-
_inheritsLoose(BufferController, _Logger);
|
18172
|
+
var BufferController = /*#__PURE__*/function () {
|
18260
18173
|
function BufferController(hls) {
|
18261
|
-
var _this;
|
18262
|
-
_this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
|
18174
|
+
var _this = this;
|
18263
18175
|
// The level details used to determine duration, target-duration and live
|
18264
|
-
|
18176
|
+
this.details = null;
|
18265
18177
|
// cache the self generated object url to detect hijack of video tag
|
18266
|
-
|
18178
|
+
this._objectUrl = null;
|
18267
18179
|
// A queue of buffer operations which require the SourceBuffer to not be updating upon execution
|
18268
|
-
|
18180
|
+
this.operationQueue = void 0;
|
18269
18181
|
// References to event listeners for each SourceBuffer, so that they can be referenced for event removal
|
18270
|
-
|
18271
|
-
|
18182
|
+
this.listeners = void 0;
|
18183
|
+
this.hls = void 0;
|
18272
18184
|
// The number of BUFFER_CODEC events received before any sourceBuffers are created
|
18273
|
-
|
18185
|
+
this.bufferCodecEventsExpected = 0;
|
18274
18186
|
// The total number of BUFFER_CODEC events received
|
18275
|
-
|
18187
|
+
this._bufferCodecEventsTotal = 0;
|
18276
18188
|
// A reference to the attached media element
|
18277
|
-
|
18189
|
+
this.media = null;
|
18278
18190
|
// A reference to the active media source
|
18279
|
-
|
18191
|
+
this.mediaSource = null;
|
18280
18192
|
// Last MP3 audio chunk appended
|
18281
|
-
|
18282
|
-
|
18193
|
+
this.lastMpegAudioChunk = null;
|
18194
|
+
this.appendSource = void 0;
|
18283
18195
|
// counters
|
18284
|
-
|
18196
|
+
this.appendErrors = {
|
18285
18197
|
audio: 0,
|
18286
18198
|
video: 0,
|
18287
18199
|
audiovideo: 0
|
18288
18200
|
};
|
18289
|
-
|
18290
|
-
|
18291
|
-
|
18292
|
-
|
18201
|
+
this.tracks = {};
|
18202
|
+
this.pendingTracks = {};
|
18203
|
+
this.sourceBuffer = void 0;
|
18204
|
+
this.log = void 0;
|
18205
|
+
this.warn = void 0;
|
18206
|
+
this.error = void 0;
|
18207
|
+
this._onEndStreaming = function (event) {
|
18293
18208
|
if (!_this.hls) {
|
18294
18209
|
return;
|
18295
18210
|
}
|
18296
18211
|
_this.hls.pauseBuffering();
|
18297
18212
|
};
|
18298
|
-
|
18213
|
+
this._onStartStreaming = function (event) {
|
18299
18214
|
if (!_this.hls) {
|
18300
18215
|
return;
|
18301
18216
|
}
|
18302
18217
|
_this.hls.resumeBuffering();
|
18303
18218
|
};
|
18304
18219
|
// Keep as arrow functions so that we can directly reference these functions directly as event listeners
|
18305
|
-
|
18306
|
-
var
|
18307
|
-
|
18308
|
-
mediaSource = _assertThisInitialize.mediaSource;
|
18220
|
+
this._onMediaSourceOpen = function () {
|
18221
|
+
var media = _this.media,
|
18222
|
+
mediaSource = _this.mediaSource;
|
18309
18223
|
_this.log('Media source opened');
|
18310
18224
|
if (media) {
|
18311
18225
|
media.removeEventListener('emptied', _this._onMediaEmptied);
|
@@ -18321,25 +18235,27 @@
|
|
18321
18235
|
}
|
18322
18236
|
_this.checkPendingTracks();
|
18323
18237
|
};
|
18324
|
-
|
18238
|
+
this._onMediaSourceClose = function () {
|
18325
18239
|
_this.log('Media source closed');
|
18326
18240
|
};
|
18327
|
-
|
18241
|
+
this._onMediaSourceEnded = function () {
|
18328
18242
|
_this.log('Media source ended');
|
18329
18243
|
};
|
18330
|
-
|
18331
|
-
var
|
18332
|
-
|
18333
|
-
_objectUrl = _assertThisInitialize2._objectUrl;
|
18244
|
+
this._onMediaEmptied = function () {
|
18245
|
+
var mediaSrc = _this.mediaSrc,
|
18246
|
+
_objectUrl = _this._objectUrl;
|
18334
18247
|
if (mediaSrc !== _objectUrl) {
|
18335
|
-
|
18248
|
+
logger.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
|
18336
18249
|
}
|
18337
18250
|
};
|
18338
|
-
|
18339
|
-
|
18340
|
-
|
18341
|
-
|
18342
|
-
|
18251
|
+
this.hls = hls;
|
18252
|
+
var logPrefix = '[buffer-controller]';
|
18253
|
+
this.appendSource = hls.config.preferManagedMediaSource;
|
18254
|
+
this.log = logger.log.bind(logger, logPrefix);
|
18255
|
+
this.warn = logger.warn.bind(logger, logPrefix);
|
18256
|
+
this.error = logger.error.bind(logger, logPrefix);
|
18257
|
+
this._initSourceBuffer();
|
18258
|
+
this.registerListeners();
|
18343
18259
|
}
|
18344
18260
|
var _proto = BufferController.prototype;
|
18345
18261
|
_proto.hasSourceTypes = function hasSourceTypes() {
|
@@ -18351,12 +18267,6 @@
|
|
18351
18267
|
this.lastMpegAudioChunk = null;
|
18352
18268
|
// @ts-ignore
|
18353
18269
|
this.hls = null;
|
18354
|
-
// @ts-ignore
|
18355
|
-
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
18356
|
-
// @ts-ignore
|
18357
|
-
this._onMediaSourceEnded = null;
|
18358
|
-
// @ts-ignore
|
18359
|
-
this._onStartStreaming = this._onEndStreaming = null;
|
18360
18270
|
};
|
18361
18271
|
_proto.registerListeners = function registerListeners() {
|
18362
18272
|
var hls = this.hls;
|
@@ -19217,7 +19127,7 @@
|
|
19217
19127
|
}
|
19218
19128
|
}]);
|
19219
19129
|
return BufferController;
|
19220
|
-
}(
|
19130
|
+
}();
|
19221
19131
|
function removeSourceChildren(node) {
|
19222
19132
|
var sourceChildren = node.querySelectorAll('source');
|
19223
19133
|
[].slice.call(sourceChildren).forEach(function (source) {
|
@@ -21656,12 +21566,14 @@
|
|
21656
21566
|
this.cea608Parser1 = this.cea608Parser2 = undefined;
|
21657
21567
|
};
|
21658
21568
|
_proto.initCea608Parsers = function initCea608Parsers() {
|
21659
|
-
|
21660
|
-
|
21661
|
-
|
21662
|
-
|
21663
|
-
|
21664
|
-
|
21569
|
+
if (this.config.enableCEA708Captions && (!this.cea608Parser1 || !this.cea608Parser2)) {
|
21570
|
+
var channel1 = new OutputFilter(this, 'textTrack1');
|
21571
|
+
var channel2 = new OutputFilter(this, 'textTrack2');
|
21572
|
+
var channel3 = new OutputFilter(this, 'textTrack3');
|
21573
|
+
var channel4 = new OutputFilter(this, 'textTrack4');
|
21574
|
+
this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
|
21575
|
+
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21576
|
+
}
|
21665
21577
|
};
|
21666
21578
|
_proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
|
21667
21579
|
// skip cues which overlap more than 50% with previously parsed time ranges
|
@@ -21896,7 +21808,7 @@
|
|
21896
21808
|
return t.label;
|
21897
21809
|
});
|
21898
21810
|
if (unusedTextTracks.length) {
|
21899
|
-
|
21811
|
+
logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
|
21900
21812
|
}
|
21901
21813
|
}
|
21902
21814
|
} else if (this.tracks.length) {
|
@@ -21942,20 +21854,23 @@
|
|
21942
21854
|
return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
|
21943
21855
|
};
|
21944
21856
|
_proto.onFragLoading = function onFragLoading(event, data) {
|
21857
|
+
this.initCea608Parsers();
|
21858
|
+
var cea608Parser1 = this.cea608Parser1,
|
21859
|
+
cea608Parser2 = this.cea608Parser2,
|
21860
|
+
lastCc = this.lastCc,
|
21861
|
+
lastSn = this.lastSn,
|
21862
|
+
lastPartIndex = this.lastPartIndex;
|
21863
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
21864
|
+
return;
|
21865
|
+
}
|
21945
21866
|
// if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
|
21946
|
-
if (
|
21867
|
+
if (data.frag.type === PlaylistLevelType.MAIN) {
|
21947
21868
|
var _data$part$index, _data$part;
|
21948
|
-
var cea608Parser1 = this.cea608Parser1,
|
21949
|
-
cea608Parser2 = this.cea608Parser2,
|
21950
|
-
lastSn = this.lastSn;
|
21951
|
-
if (!cea608Parser1 || !cea608Parser2) {
|
21952
|
-
return;
|
21953
|
-
}
|
21954
21869
|
var _data$frag = data.frag,
|
21955
21870
|
cc = _data$frag.cc,
|
21956
21871
|
sn = _data$frag.sn;
|
21957
|
-
var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
21958
|
-
if (!(sn === lastSn + 1 || sn === lastSn && partIndex ===
|
21872
|
+
var partIndex = (_data$part$index = data == null ? void 0 : (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
21873
|
+
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
|
21959
21874
|
cea608Parser1.reset();
|
21960
21875
|
cea608Parser2.reset();
|
21961
21876
|
}
|
@@ -22011,7 +21926,7 @@
|
|
22011
21926
|
frag: frag
|
22012
21927
|
});
|
22013
21928
|
}, function (error) {
|
22014
|
-
|
21929
|
+
logger.log("Failed to parse IMSC1: " + error);
|
22015
21930
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
22016
21931
|
success: false,
|
22017
21932
|
frag: frag,
|
@@ -22049,7 +21964,7 @@
|
|
22049
21964
|
_this5._fallbackToIMSC1(frag, payload);
|
22050
21965
|
}
|
22051
21966
|
// Something went wrong while parsing. Trigger event with success false.
|
22052
|
-
|
21967
|
+
logger.log("Failed to parse VTT cue: " + error);
|
22053
21968
|
if (missingInitPTS && maxAvCC > frag.cc) {
|
22054
21969
|
return;
|
22055
21970
|
}
|
@@ -22111,7 +22026,10 @@
|
|
22111
22026
|
this.captionsTracks = {};
|
22112
22027
|
};
|
22113
22028
|
_proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
|
22114
|
-
|
22029
|
+
this.initCea608Parsers();
|
22030
|
+
var cea608Parser1 = this.cea608Parser1,
|
22031
|
+
cea608Parser2 = this.cea608Parser2;
|
22032
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
22115
22033
|
return;
|
22116
22034
|
}
|
22117
22035
|
var frag = data.frag,
|
@@ -22124,12 +22042,9 @@
|
|
22124
22042
|
for (var i = 0; i < samples.length; i++) {
|
22125
22043
|
var ccBytes = samples[i].bytes;
|
22126
22044
|
if (ccBytes) {
|
22127
|
-
if (!this.cea608Parser1) {
|
22128
|
-
this.initCea608Parsers();
|
22129
|
-
}
|
22130
22045
|
var ccdatas = this.extractCea608Data(ccBytes);
|
22131
|
-
|
22132
|
-
|
22046
|
+
cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22047
|
+
cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22133
22048
|
}
|
22134
22049
|
}
|
22135
22050
|
};
|
@@ -22321,7 +22236,7 @@
|
|
22321
22236
|
var hls = this.hls;
|
22322
22237
|
var maxLevel = this.getMaxLevel(levels.length - 1);
|
22323
22238
|
if (maxLevel !== this.autoLevelCapping) {
|
22324
|
-
|
22239
|
+
logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
22325
22240
|
}
|
22326
22241
|
hls.autoLevelCapping = maxLevel;
|
22327
22242
|
if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
|
@@ -22511,10 +22426,10 @@
|
|
22511
22426
|
totalDroppedFrames: droppedFrames
|
22512
22427
|
});
|
22513
22428
|
if (droppedFPS > 0) {
|
22514
|
-
//
|
22429
|
+
// logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
22515
22430
|
if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
|
22516
22431
|
var currentLevel = hls.currentLevel;
|
22517
|
-
|
22432
|
+
logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
22518
22433
|
if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
|
22519
22434
|
currentLevel = currentLevel - 1;
|
22520
22435
|
hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
|
@@ -22547,6 +22462,7 @@
|
|
22547
22462
|
return FPSController;
|
22548
22463
|
}();
|
22549
22464
|
|
22465
|
+
var LOGGER_PREFIX = '[eme]';
|
22550
22466
|
/**
|
22551
22467
|
* Controller to deal with encrypted media extensions (EME)
|
22552
22468
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
|
@@ -22554,122 +22470,26 @@
|
|
22554
22470
|
* @class
|
22555
22471
|
* @constructor
|
22556
22472
|
*/
|
22557
|
-
var EMEController = /*#__PURE__*/function (
|
22558
|
-
_inheritsLoose(EMEController, _Logger);
|
22473
|
+
var EMEController = /*#__PURE__*/function () {
|
22559
22474
|
function EMEController(hls) {
|
22560
|
-
|
22561
|
-
|
22562
|
-
|
22563
|
-
|
22564
|
-
|
22565
|
-
|
22566
|
-
|
22567
|
-
|
22568
|
-
|
22569
|
-
|
22570
|
-
|
22571
|
-
|
22572
|
-
|
22573
|
-
|
22574
|
-
|
22575
|
-
|
22576
|
-
|
22577
|
-
|
22578
|
-
return;
|
22579
|
-
}
|
22580
|
-
var keyId;
|
22581
|
-
var keySystemDomain;
|
22582
|
-
if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22583
|
-
// Match sinf keyId to playlist skd://keyId=
|
22584
|
-
var json = bin2str(new Uint8Array(initData));
|
22585
|
-
try {
|
22586
|
-
var sinf = base64Decode(JSON.parse(json).sinf);
|
22587
|
-
var tenc = parseSinf(new Uint8Array(sinf));
|
22588
|
-
if (!tenc) {
|
22589
|
-
return;
|
22590
|
-
}
|
22591
|
-
keyId = tenc.subarray(8, 24);
|
22592
|
-
keySystemDomain = KeySystems.FAIRPLAY;
|
22593
|
-
} catch (error) {
|
22594
|
-
_this.warn('Failed to parse sinf "encrypted" event message initData');
|
22595
|
-
return;
|
22596
|
-
}
|
22597
|
-
} else {
|
22598
|
-
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22599
|
-
var psshInfo = parsePssh(initData);
|
22600
|
-
if (psshInfo === null) {
|
22601
|
-
return;
|
22602
|
-
}
|
22603
|
-
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22604
|
-
keyId = psshInfo.data.subarray(8, 24);
|
22605
|
-
}
|
22606
|
-
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22607
|
-
}
|
22608
|
-
if (!keySystemDomain || !keyId) {
|
22609
|
-
return;
|
22610
|
-
}
|
22611
|
-
var keyIdHex = Hex.hexDump(keyId);
|
22612
|
-
var _assertThisInitialize = _assertThisInitialized(_this),
|
22613
|
-
keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
|
22614
|
-
mediaKeySessions = _assertThisInitialize.mediaKeySessions;
|
22615
|
-
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22616
|
-
var _loop = function _loop() {
|
22617
|
-
// Match playlist key
|
22618
|
-
var keyContext = mediaKeySessions[i];
|
22619
|
-
var decryptdata = keyContext.decryptdata;
|
22620
|
-
if (decryptdata.pssh || !decryptdata.keyId) {
|
22621
|
-
return 0; // continue
|
22622
|
-
}
|
22623
|
-
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22624
|
-
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22625
|
-
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22626
|
-
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22627
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22628
|
-
decryptdata.keyId = keyId;
|
22629
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22630
|
-
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22631
|
-
});
|
22632
|
-
return 1; // break
|
22633
|
-
}
|
22634
|
-
},
|
22635
|
-
_ret;
|
22636
|
-
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22637
|
-
_ret = _loop();
|
22638
|
-
if (_ret === 0) continue;
|
22639
|
-
if (_ret === 1) break;
|
22640
|
-
}
|
22641
|
-
if (!keySessionContextPromise) {
|
22642
|
-
// Clear-lead key (not encountered in playlist)
|
22643
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
22644
|
-
var _keySystemToKeySystem;
|
22645
|
-
var keySystem = _ref.keySystem,
|
22646
|
-
mediaKeys = _ref.mediaKeys;
|
22647
|
-
_this.throwIfDestroyed();
|
22648
|
-
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22649
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22650
|
-
decryptdata.keyId = keyId;
|
22651
|
-
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22652
|
-
_this.throwIfDestroyed();
|
22653
|
-
var keySessionContext = _this.createMediaKeySessionContext({
|
22654
|
-
decryptdata: decryptdata,
|
22655
|
-
keySystem: keySystem,
|
22656
|
-
mediaKeys: mediaKeys
|
22657
|
-
});
|
22658
|
-
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22659
|
-
});
|
22660
|
-
});
|
22661
|
-
}
|
22662
|
-
keySessionContextPromise.catch(function (error) {
|
22663
|
-
return _this.handleError(error);
|
22664
|
-
});
|
22665
|
-
};
|
22666
|
-
_this.onWaitingForKey = function (event) {
|
22667
|
-
_this.log("\"" + event.type + "\" event");
|
22668
|
-
};
|
22669
|
-
_this.hls = hls;
|
22670
|
-
_this.config = hls.config;
|
22671
|
-
_this.registerListeners();
|
22672
|
-
return _this;
|
22475
|
+
this.hls = void 0;
|
22476
|
+
this.config = void 0;
|
22477
|
+
this.media = null;
|
22478
|
+
this.keyFormatPromise = null;
|
22479
|
+
this.keySystemAccessPromises = {};
|
22480
|
+
this._requestLicenseFailureCount = 0;
|
22481
|
+
this.mediaKeySessions = [];
|
22482
|
+
this.keyIdToKeySessionPromise = {};
|
22483
|
+
this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
22484
|
+
this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
|
22485
|
+
this.onWaitingForKey = this._onWaitingForKey.bind(this);
|
22486
|
+
this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
|
22487
|
+
this.log = logger.log.bind(logger, LOGGER_PREFIX);
|
22488
|
+
this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
|
22489
|
+
this.error = logger.error.bind(logger, LOGGER_PREFIX);
|
22490
|
+
this.hls = hls;
|
22491
|
+
this.config = hls.config;
|
22492
|
+
this.registerListeners();
|
22673
22493
|
}
|
22674
22494
|
var _proto = EMEController.prototype;
|
22675
22495
|
_proto.destroy = function destroy() {
|
@@ -22681,9 +22501,9 @@
|
|
22681
22501
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
22682
22502
|
config.drmSystems = config.drmSystemOptions = {};
|
22683
22503
|
// @ts-ignore
|
22684
|
-
this.hls = this.
|
22504
|
+
this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
|
22685
22505
|
// @ts-ignore
|
22686
|
-
this.
|
22506
|
+
this.config = null;
|
22687
22507
|
};
|
22688
22508
|
_proto.registerListeners = function registerListeners() {
|
22689
22509
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -22722,7 +22542,7 @@
|
|
22722
22542
|
}
|
22723
22543
|
};
|
22724
22544
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
22725
|
-
var
|
22545
|
+
var _this = this;
|
22726
22546
|
var levels = this.hls.levels;
|
22727
22547
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
22728
22548
|
return !!value && a.indexOf(value) === i;
|
@@ -22739,7 +22559,7 @@
|
|
22739
22559
|
return new Promise(function (resolve, reject) {
|
22740
22560
|
var attempt = function attempt(keySystems) {
|
22741
22561
|
var keySystem = keySystems.shift();
|
22742
|
-
|
22562
|
+
_this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
22743
22563
|
return resolve({
|
22744
22564
|
keySystem: keySystem,
|
22745
22565
|
mediaKeys: mediaKeys
|
@@ -22774,7 +22594,7 @@
|
|
22774
22594
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
22775
22595
|
};
|
22776
22596
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
22777
|
-
var
|
22597
|
+
var _this2 = this;
|
22778
22598
|
// This can throw, but is caught in event handler callpath
|
22779
22599
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
22780
22600
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -22786,23 +22606,23 @@
|
|
22786
22606
|
keySystemAccess: keySystemAccess
|
22787
22607
|
};
|
22788
22608
|
keySystemAccess.catch(function (error) {
|
22789
|
-
|
22609
|
+
_this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
22790
22610
|
});
|
22791
22611
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
22792
|
-
|
22793
|
-
var certificateRequest =
|
22794
|
-
|
22612
|
+
_this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
22613
|
+
var certificateRequest = _this2.fetchServerCertificate(keySystem);
|
22614
|
+
_this2.log("Create media-keys for \"" + keySystem + "\"");
|
22795
22615
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
22796
|
-
|
22616
|
+
_this2.log("Media-keys created for \"" + keySystem + "\"");
|
22797
22617
|
return certificateRequest.then(function (certificate) {
|
22798
22618
|
if (certificate) {
|
22799
|
-
return
|
22619
|
+
return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
22800
22620
|
}
|
22801
22621
|
return mediaKeys;
|
22802
22622
|
});
|
22803
22623
|
});
|
22804
22624
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
22805
|
-
|
22625
|
+
_this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
22806
22626
|
});
|
22807
22627
|
return _keySystemAccessPromises.mediaKeys;
|
22808
22628
|
});
|
@@ -22811,10 +22631,10 @@
|
|
22811
22631
|
return keySystemAccessPromises.mediaKeys;
|
22812
22632
|
});
|
22813
22633
|
};
|
22814
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
22815
|
-
var decryptdata =
|
22816
|
-
keySystem =
|
22817
|
-
mediaKeys =
|
22634
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
|
22635
|
+
var decryptdata = _ref.decryptdata,
|
22636
|
+
keySystem = _ref.keySystem,
|
22637
|
+
mediaKeys = _ref.mediaKeys;
|
22818
22638
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
22819
22639
|
var mediaKeysSession = mediaKeys.createSession();
|
22820
22640
|
var mediaKeySessionContext = {
|
@@ -22863,14 +22683,14 @@
|
|
22863
22683
|
return this.keyFormatPromise;
|
22864
22684
|
};
|
22865
22685
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
22866
|
-
var
|
22686
|
+
var _this3 = this;
|
22867
22687
|
return new Promise(function (resolve, reject) {
|
22868
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
22688
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
|
22869
22689
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
22870
22690
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
22871
22691
|
});
|
22872
|
-
return
|
22873
|
-
var keySystem =
|
22692
|
+
return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
|
22693
|
+
var keySystem = _ref2.keySystem;
|
22874
22694
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
22875
22695
|
if (keySystemFormat) {
|
22876
22696
|
resolve(keySystemFormat);
|
@@ -22881,31 +22701,31 @@
|
|
22881
22701
|
});
|
22882
22702
|
};
|
22883
22703
|
_proto.loadKey = function loadKey(data) {
|
22884
|
-
var
|
22704
|
+
var _this4 = this;
|
22885
22705
|
var decryptdata = data.keyInfo.decryptdata;
|
22886
22706
|
var keyId = this.getKeyIdString(decryptdata);
|
22887
22707
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
22888
22708
|
this.log("Starting session for key " + keyDetails);
|
22889
22709
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
22890
22710
|
if (!keySessionContextPromise) {
|
22891
|
-
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (
|
22892
|
-
var keySystem =
|
22893
|
-
mediaKeys =
|
22894
|
-
|
22895
|
-
|
22896
|
-
return
|
22897
|
-
|
22898
|
-
var keySessionContext =
|
22711
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) {
|
22712
|
+
var keySystem = _ref3.keySystem,
|
22713
|
+
mediaKeys = _ref3.mediaKeys;
|
22714
|
+
_this4.throwIfDestroyed();
|
22715
|
+
_this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
22716
|
+
return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22717
|
+
_this4.throwIfDestroyed();
|
22718
|
+
var keySessionContext = _this4.createMediaKeySessionContext({
|
22899
22719
|
keySystem: keySystem,
|
22900
22720
|
mediaKeys: mediaKeys,
|
22901
22721
|
decryptdata: decryptdata
|
22902
22722
|
});
|
22903
22723
|
var scheme = 'cenc';
|
22904
|
-
return
|
22724
|
+
return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
22905
22725
|
});
|
22906
22726
|
});
|
22907
22727
|
keySessionContextPromise.catch(function (error) {
|
22908
|
-
return
|
22728
|
+
return _this4.handleError(error);
|
22909
22729
|
});
|
22910
22730
|
}
|
22911
22731
|
return keySessionContextPromise;
|
@@ -22956,6 +22776,104 @@
|
|
22956
22776
|
}
|
22957
22777
|
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22958
22778
|
};
|
22779
|
+
_proto._onMediaEncrypted = function _onMediaEncrypted(event) {
|
22780
|
+
var _this5 = this;
|
22781
|
+
var initDataType = event.initDataType,
|
22782
|
+
initData = event.initData;
|
22783
|
+
this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
22784
|
+
|
22785
|
+
// Ignore event when initData is null
|
22786
|
+
if (initData === null) {
|
22787
|
+
return;
|
22788
|
+
}
|
22789
|
+
var keyId;
|
22790
|
+
var keySystemDomain;
|
22791
|
+
if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22792
|
+
// Match sinf keyId to playlist skd://keyId=
|
22793
|
+
var json = bin2str(new Uint8Array(initData));
|
22794
|
+
try {
|
22795
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
22796
|
+
var tenc = parseSinf(new Uint8Array(sinf));
|
22797
|
+
if (!tenc) {
|
22798
|
+
return;
|
22799
|
+
}
|
22800
|
+
keyId = tenc.subarray(8, 24);
|
22801
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
22802
|
+
} catch (error) {
|
22803
|
+
this.warn('Failed to parse sinf "encrypted" event message initData');
|
22804
|
+
return;
|
22805
|
+
}
|
22806
|
+
} else {
|
22807
|
+
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22808
|
+
var psshInfo = parsePssh(initData);
|
22809
|
+
if (psshInfo === null) {
|
22810
|
+
return;
|
22811
|
+
}
|
22812
|
+
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22813
|
+
keyId = psshInfo.data.subarray(8, 24);
|
22814
|
+
}
|
22815
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22816
|
+
}
|
22817
|
+
if (!keySystemDomain || !keyId) {
|
22818
|
+
return;
|
22819
|
+
}
|
22820
|
+
var keyIdHex = Hex.hexDump(keyId);
|
22821
|
+
var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
|
22822
|
+
mediaKeySessions = this.mediaKeySessions;
|
22823
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22824
|
+
var _loop = function _loop() {
|
22825
|
+
// Match playlist key
|
22826
|
+
var keyContext = mediaKeySessions[i];
|
22827
|
+
var decryptdata = keyContext.decryptdata;
|
22828
|
+
if (decryptdata.pssh || !decryptdata.keyId) {
|
22829
|
+
return 0; // continue
|
22830
|
+
}
|
22831
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22832
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22833
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22834
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22835
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22836
|
+
decryptdata.keyId = keyId;
|
22837
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22838
|
+
return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22839
|
+
});
|
22840
|
+
return 1; // break
|
22841
|
+
}
|
22842
|
+
},
|
22843
|
+
_ret;
|
22844
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22845
|
+
_ret = _loop();
|
22846
|
+
if (_ret === 0) continue;
|
22847
|
+
if (_ret === 1) break;
|
22848
|
+
}
|
22849
|
+
if (!keySessionContextPromise) {
|
22850
|
+
// Clear-lead key (not encountered in playlist)
|
22851
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
|
22852
|
+
var _keySystemToKeySystem;
|
22853
|
+
var keySystem = _ref4.keySystem,
|
22854
|
+
mediaKeys = _ref4.mediaKeys;
|
22855
|
+
_this5.throwIfDestroyed();
|
22856
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22857
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22858
|
+
decryptdata.keyId = keyId;
|
22859
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22860
|
+
_this5.throwIfDestroyed();
|
22861
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22862
|
+
decryptdata: decryptdata,
|
22863
|
+
keySystem: keySystem,
|
22864
|
+
mediaKeys: mediaKeys
|
22865
|
+
});
|
22866
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22867
|
+
});
|
22868
|
+
});
|
22869
|
+
}
|
22870
|
+
keySessionContextPromise.catch(function (error) {
|
22871
|
+
return _this5.handleError(error);
|
22872
|
+
});
|
22873
|
+
};
|
22874
|
+
_proto._onWaitingForKey = function _onWaitingForKey(event) {
|
22875
|
+
this.log("\"" + event.type + "\" event");
|
22876
|
+
};
|
22959
22877
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
22960
22878
|
var _this6 = this;
|
22961
22879
|
var queue = this.setMediaKeysQueue.slice();
|
@@ -23411,7 +23329,7 @@
|
|
23411
23329
|
}
|
23412
23330
|
};
|
23413
23331
|
return EMEController;
|
23414
|
-
}(
|
23332
|
+
}();
|
23415
23333
|
EMEController.CDMCleanupPromise = void 0;
|
23416
23334
|
var EMEKeyError = /*#__PURE__*/function (_Error) {
|
23417
23335
|
_inheritsLoose(EMEKeyError, _Error);
|
@@ -24737,28 +24655,26 @@
|
|
24737
24655
|
}();
|
24738
24656
|
|
24739
24657
|
var PATHWAY_PENALTY_DURATION_MS = 300000;
|
24740
|
-
var ContentSteeringController = /*#__PURE__*/function (
|
24741
|
-
_inheritsLoose(ContentSteeringController, _Logger);
|
24658
|
+
var ContentSteeringController = /*#__PURE__*/function () {
|
24742
24659
|
function ContentSteeringController(hls) {
|
24743
|
-
|
24744
|
-
|
24745
|
-
|
24746
|
-
|
24747
|
-
|
24748
|
-
|
24749
|
-
|
24750
|
-
|
24751
|
-
|
24752
|
-
|
24753
|
-
|
24754
|
-
|
24755
|
-
|
24756
|
-
|
24757
|
-
|
24758
|
-
|
24759
|
-
|
24760
|
-
|
24761
|
-
return _this;
|
24660
|
+
this.hls = void 0;
|
24661
|
+
this.log = void 0;
|
24662
|
+
this.loader = null;
|
24663
|
+
this.uri = null;
|
24664
|
+
this.pathwayId = '.';
|
24665
|
+
this.pathwayPriority = null;
|
24666
|
+
this.timeToLoad = 300;
|
24667
|
+
this.reloadTimer = -1;
|
24668
|
+
this.updated = 0;
|
24669
|
+
this.started = false;
|
24670
|
+
this.enabled = true;
|
24671
|
+
this.levels = null;
|
24672
|
+
this.audioTracks = null;
|
24673
|
+
this.subtitleTracks = null;
|
24674
|
+
this.penalizedPathways = {};
|
24675
|
+
this.hls = hls;
|
24676
|
+
this.log = logger.log.bind(logger, "[content-steering]:");
|
24677
|
+
this.registerListeners();
|
24762
24678
|
}
|
24763
24679
|
var _proto = ContentSteeringController.prototype;
|
24764
24680
|
_proto.registerListeners = function registerListeners() {
|
@@ -24879,7 +24795,7 @@
|
|
24879
24795
|
errorAction.resolved = this.pathwayId !== errorPathway;
|
24880
24796
|
}
|
24881
24797
|
if (!errorAction.resolved) {
|
24882
|
-
|
24798
|
+
logger.warn("Could not resolve " + data.details + " (\"" + data.error.message + "\") with content-steering for Pathway: " + errorPathway + " levels: " + (levels ? levels.length : levels) + " priorities: " + JSON.stringify(pathwayPriority) + " penalized: " + JSON.stringify(this.penalizedPathways));
|
24883
24799
|
}
|
24884
24800
|
}
|
24885
24801
|
};
|
@@ -24959,7 +24875,7 @@
|
|
24959
24875
|
return defaultPathway;
|
24960
24876
|
};
|
24961
24877
|
_proto.clonePathways = function clonePathways(pathwayClones) {
|
24962
|
-
var
|
24878
|
+
var _this = this;
|
24963
24879
|
var levels = this.levels;
|
24964
24880
|
if (!levels) {
|
24965
24881
|
return;
|
@@ -24975,7 +24891,7 @@
|
|
24975
24891
|
})) {
|
24976
24892
|
return;
|
24977
24893
|
}
|
24978
|
-
var clonedVariants =
|
24894
|
+
var clonedVariants = _this.getLevelsForPathway(baseId).map(function (baseLevel) {
|
24979
24895
|
var attributes = new AttrList(baseLevel.attrs);
|
24980
24896
|
attributes['PATHWAY-ID'] = cloneId;
|
24981
24897
|
var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
|
@@ -25012,12 +24928,12 @@
|
|
25012
24928
|
return clonedLevel;
|
25013
24929
|
});
|
25014
24930
|
levels.push.apply(levels, clonedVariants);
|
25015
|
-
cloneRenditionGroups(
|
25016
|
-
cloneRenditionGroups(
|
24931
|
+
cloneRenditionGroups(_this.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
|
24932
|
+
cloneRenditionGroups(_this.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
|
25017
24933
|
});
|
25018
24934
|
};
|
25019
24935
|
_proto.loadSteeringManifest = function loadSteeringManifest(uri) {
|
25020
|
-
var
|
24936
|
+
var _this2 = this;
|
25021
24937
|
var config = this.hls.config;
|
25022
24938
|
var Loader = config.loader;
|
25023
24939
|
if (this.loader) {
|
@@ -25052,87 +24968,87 @@
|
|
25052
24968
|
};
|
25053
24969
|
var callbacks = {
|
25054
24970
|
onSuccess: function onSuccess(response, stats, context, networkDetails) {
|
25055
|
-
|
24971
|
+
_this2.log("Loaded steering manifest: \"" + url + "\"");
|
25056
24972
|
var steeringData = response.data;
|
25057
|
-
if (
|
25058
|
-
|
24973
|
+
if (steeringData.VERSION !== 1) {
|
24974
|
+
_this2.log("Steering VERSION " + steeringData.VERSION + " not supported!");
|
25059
24975
|
return;
|
25060
24976
|
}
|
25061
|
-
|
25062
|
-
|
24977
|
+
_this2.updated = performance.now();
|
24978
|
+
_this2.timeToLoad = steeringData.TTL;
|
25063
24979
|
var reloadUri = steeringData['RELOAD-URI'],
|
25064
24980
|
pathwayClones = steeringData['PATHWAY-CLONES'],
|
25065
24981
|
pathwayPriority = steeringData['PATHWAY-PRIORITY'];
|
25066
24982
|
if (reloadUri) {
|
25067
24983
|
try {
|
25068
|
-
|
24984
|
+
_this2.uri = new self.URL(reloadUri, url).href;
|
25069
24985
|
} catch (error) {
|
25070
|
-
|
25071
|
-
|
24986
|
+
_this2.enabled = false;
|
24987
|
+
_this2.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
|
25072
24988
|
return;
|
25073
24989
|
}
|
25074
24990
|
}
|
25075
|
-
|
24991
|
+
_this2.scheduleRefresh(_this2.uri || context.url);
|
25076
24992
|
if (pathwayClones) {
|
25077
|
-
|
24993
|
+
_this2.clonePathways(pathwayClones);
|
25078
24994
|
}
|
25079
24995
|
var loadedSteeringData = {
|
25080
24996
|
steeringManifest: steeringData,
|
25081
24997
|
url: url.toString()
|
25082
24998
|
};
|
25083
|
-
|
24999
|
+
_this2.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
|
25084
25000
|
if (pathwayPriority) {
|
25085
|
-
|
25001
|
+
_this2.updatePathwayPriority(pathwayPriority);
|
25086
25002
|
}
|
25087
25003
|
},
|
25088
25004
|
onError: function onError(error, context, networkDetails, stats) {
|
25089
|
-
|
25090
|
-
|
25005
|
+
_this2.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
|
25006
|
+
_this2.stopLoad();
|
25091
25007
|
if (error.code === 410) {
|
25092
|
-
|
25093
|
-
|
25008
|
+
_this2.enabled = false;
|
25009
|
+
_this2.log("Steering manifest " + context.url + " no longer available");
|
25094
25010
|
return;
|
25095
25011
|
}
|
25096
|
-
var ttl =
|
25012
|
+
var ttl = _this2.timeToLoad * 1000;
|
25097
25013
|
if (error.code === 429) {
|
25098
|
-
var loader =
|
25014
|
+
var loader = _this2.loader;
|
25099
25015
|
if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
|
25100
25016
|
var retryAfter = loader.getResponseHeader('Retry-After');
|
25101
25017
|
if (retryAfter) {
|
25102
25018
|
ttl = parseFloat(retryAfter) * 1000;
|
25103
25019
|
}
|
25104
25020
|
}
|
25105
|
-
|
25021
|
+
_this2.log("Steering manifest " + context.url + " rate limited");
|
25106
25022
|
return;
|
25107
25023
|
}
|
25108
|
-
|
25024
|
+
_this2.scheduleRefresh(_this2.uri || context.url, ttl);
|
25109
25025
|
},
|
25110
25026
|
onTimeout: function onTimeout(stats, context, networkDetails) {
|
25111
|
-
|
25112
|
-
|
25027
|
+
_this2.log("Timeout loading steering manifest (" + context.url + ")");
|
25028
|
+
_this2.scheduleRefresh(_this2.uri || context.url);
|
25113
25029
|
}
|
25114
25030
|
};
|
25115
25031
|
this.log("Requesting steering manifest: " + url);
|
25116
25032
|
this.loader.load(context, loaderConfig, callbacks);
|
25117
25033
|
};
|
25118
25034
|
_proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
|
25119
|
-
var
|
25035
|
+
var _this3 = this;
|
25120
25036
|
if (ttlMs === void 0) {
|
25121
25037
|
ttlMs = this.timeToLoad * 1000;
|
25122
25038
|
}
|
25123
25039
|
this.clearTimeout();
|
25124
25040
|
this.reloadTimer = self.setTimeout(function () {
|
25125
|
-
var
|
25126
|
-
var media = (
|
25041
|
+
var _this3$hls;
|
25042
|
+
var media = (_this3$hls = _this3.hls) == null ? void 0 : _this3$hls.media;
|
25127
25043
|
if (media && !media.ended) {
|
25128
|
-
|
25044
|
+
_this3.loadSteeringManifest(uri);
|
25129
25045
|
return;
|
25130
25046
|
}
|
25131
|
-
|
25047
|
+
_this3.scheduleRefresh(uri, _this3.timeToLoad * 1000);
|
25132
25048
|
}, ttlMs);
|
25133
25049
|
};
|
25134
25050
|
return ContentSteeringController;
|
25135
|
-
}(
|
25051
|
+
}();
|
25136
25052
|
function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
|
25137
25053
|
if (!tracks) {
|
25138
25054
|
return;
|
@@ -26032,7 +25948,7 @@
|
|
26032
25948
|
/**
|
26033
25949
|
* @ignore
|
26034
25950
|
*/
|
26035
|
-
function mergeConfig(defaultConfig, userConfig
|
25951
|
+
function mergeConfig(defaultConfig, userConfig) {
|
26036
25952
|
if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
|
26037
25953
|
throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
|
26038
25954
|
}
|
@@ -26102,7 +26018,7 @@
|
|
26102
26018
|
/**
|
26103
26019
|
* @ignore
|
26104
26020
|
*/
|
26105
|
-
function enableStreamingMode(config
|
26021
|
+
function enableStreamingMode(config) {
|
26106
26022
|
var currentLoader = config.loader;
|
26107
26023
|
if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
|
26108
26024
|
// If a developer has configured their own loader, respect that choice
|
@@ -26119,11 +26035,12 @@
|
|
26119
26035
|
}
|
26120
26036
|
}
|
26121
26037
|
|
26038
|
+
var chromeOrFirefox;
|
26122
26039
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
26123
26040
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
26124
26041
|
function LevelController(hls, contentSteeringController) {
|
26125
26042
|
var _this;
|
26126
|
-
_this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
|
26043
|
+
_this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this;
|
26127
26044
|
_this._levels = [];
|
26128
26045
|
_this._firstLevel = -1;
|
26129
26046
|
_this._maxAutoLevel = -1;
|
@@ -26192,13 +26109,21 @@
|
|
26192
26109
|
var videoCodecFound = false;
|
26193
26110
|
var audioCodecFound = false;
|
26194
26111
|
data.levels.forEach(function (levelParsed) {
|
26195
|
-
var _videoCodec;
|
26112
|
+
var _audioCodec, _videoCodec;
|
26196
26113
|
var attributes = levelParsed.attrs;
|
26114
|
+
|
26115
|
+
// erase audio codec info if browser does not support mp4a.40.34.
|
26116
|
+
// demuxer will autodetect codec and fallback to mpeg/audio
|
26197
26117
|
var audioCodec = levelParsed.audioCodec,
|
26198
26118
|
videoCodec = levelParsed.videoCodec;
|
26119
|
+
if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
|
26120
|
+
chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
|
26121
|
+
if (chromeOrFirefox) {
|
26122
|
+
levelParsed.audioCodec = audioCodec = undefined;
|
26123
|
+
}
|
26124
|
+
}
|
26199
26125
|
if (audioCodec) {
|
26200
|
-
|
26201
|
-
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
26126
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
|
26202
26127
|
}
|
26203
26128
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
26204
26129
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -26321,8 +26246,8 @@
|
|
26321
26246
|
return _valueB - _valueA;
|
26322
26247
|
}
|
26323
26248
|
}
|
26324
|
-
if (a.
|
26325
|
-
return a.
|
26249
|
+
if (a.averageBitrate !== b.averageBitrate) {
|
26250
|
+
return a.averageBitrate - b.averageBitrate;
|
26326
26251
|
}
|
26327
26252
|
return 0;
|
26328
26253
|
});
|
@@ -26806,8 +26731,6 @@
|
|
26806
26731
|
}
|
26807
26732
|
return this.loadKeyEME(keyInfo, frag);
|
26808
26733
|
case 'AES-128':
|
26809
|
-
case 'AES-256':
|
26810
|
-
case 'AES-256-CTR':
|
26811
26734
|
return this.loadKeyHTTP(keyInfo, frag);
|
26812
26735
|
default:
|
26813
26736
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -26947,25 +26870,21 @@
|
|
26947
26870
|
var MAX_START_GAP_JUMP = 2.0;
|
26948
26871
|
var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
|
26949
26872
|
var SKIP_BUFFER_RANGE_START = 0.05;
|
26950
|
-
var GapController = /*#__PURE__*/function (
|
26951
|
-
_inheritsLoose(GapController, _Logger);
|
26873
|
+
var GapController = /*#__PURE__*/function () {
|
26952
26874
|
function GapController(config, media, fragmentTracker, hls) {
|
26953
|
-
|
26954
|
-
|
26955
|
-
|
26956
|
-
|
26957
|
-
|
26958
|
-
|
26959
|
-
|
26960
|
-
|
26961
|
-
|
26962
|
-
|
26963
|
-
|
26964
|
-
|
26965
|
-
|
26966
|
-
_this.fragmentTracker = fragmentTracker;
|
26967
|
-
_this.hls = hls;
|
26968
|
-
return _this;
|
26875
|
+
this.config = void 0;
|
26876
|
+
this.media = null;
|
26877
|
+
this.fragmentTracker = void 0;
|
26878
|
+
this.hls = void 0;
|
26879
|
+
this.nudgeRetry = 0;
|
26880
|
+
this.stallReported = false;
|
26881
|
+
this.stalled = null;
|
26882
|
+
this.moved = false;
|
26883
|
+
this.seeking = false;
|
26884
|
+
this.config = config;
|
26885
|
+
this.media = media;
|
26886
|
+
this.fragmentTracker = fragmentTracker;
|
26887
|
+
this.hls = hls;
|
26969
26888
|
}
|
26970
26889
|
var _proto = GapController.prototype;
|
26971
26890
|
_proto.destroy = function destroy() {
|
@@ -27003,7 +26922,7 @@
|
|
27003
26922
|
// The playhead is now moving, but was previously stalled
|
27004
26923
|
if (this.stallReported) {
|
27005
26924
|
var _stalledDuration = self.performance.now() - stalled;
|
27006
|
-
|
26925
|
+
logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
|
27007
26926
|
this.stallReported = false;
|
27008
26927
|
}
|
27009
26928
|
this.stalled = null;
|
@@ -27112,7 +27031,7 @@
|
|
27112
27031
|
// needs to cross some sort of threshold covering all source-buffers content
|
27113
27032
|
// to start playing properly.
|
27114
27033
|
if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
|
27115
|
-
|
27034
|
+
logger.warn('Trying to nudge playhead over buffer-hole');
|
27116
27035
|
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
|
27117
27036
|
// We only try to jump the hole if it's under the configured size
|
27118
27037
|
// Reset stalled so to rearm watchdog timer
|
@@ -27134,7 +27053,7 @@
|
|
27134
27053
|
// Report stalled error once
|
27135
27054
|
this.stallReported = true;
|
27136
27055
|
var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
|
27137
|
-
|
27056
|
+
logger.warn(error.message);
|
27138
27057
|
hls.trigger(Events.ERROR, {
|
27139
27058
|
type: ErrorTypes.MEDIA_ERROR,
|
27140
27059
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27198,7 +27117,7 @@
|
|
27198
27117
|
}
|
27199
27118
|
}
|
27200
27119
|
var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
|
27201
|
-
|
27120
|
+
logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
|
27202
27121
|
this.moved = true;
|
27203
27122
|
this.stalled = null;
|
27204
27123
|
media.currentTime = targetTime;
|
@@ -27237,7 +27156,7 @@
|
|
27237
27156
|
var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
|
27238
27157
|
// playback stalled in buffered area ... let's nudge currentTime to try to overcome this
|
27239
27158
|
var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
|
27240
|
-
|
27159
|
+
logger.warn(error.message);
|
27241
27160
|
media.currentTime = targetTime;
|
27242
27161
|
hls.trigger(Events.ERROR, {
|
27243
27162
|
type: ErrorTypes.MEDIA_ERROR,
|
@@ -27247,7 +27166,7 @@
|
|
27247
27166
|
});
|
27248
27167
|
} else {
|
27249
27168
|
var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
|
27250
|
-
|
27169
|
+
logger.error(_error.message);
|
27251
27170
|
hls.trigger(Events.ERROR, {
|
27252
27171
|
type: ErrorTypes.MEDIA_ERROR,
|
27253
27172
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27257,14 +27176,14 @@
|
|
27257
27176
|
}
|
27258
27177
|
};
|
27259
27178
|
return GapController;
|
27260
|
-
}(
|
27179
|
+
}();
|
27261
27180
|
|
27262
27181
|
var TICK_INTERVAL = 100; // how often to tick in ms
|
27263
27182
|
var StreamController = /*#__PURE__*/function (_BaseStreamController) {
|
27264
27183
|
_inheritsLoose(StreamController, _BaseStreamController);
|
27265
27184
|
function StreamController(hls, fragmentTracker, keyLoader) {
|
27266
27185
|
var _this;
|
27267
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
|
27186
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]', PlaylistLevelType.MAIN) || this;
|
27268
27187
|
_this.audioCodecSwap = false;
|
27269
27188
|
_this.gapController = null;
|
27270
27189
|
_this.level = -1;
|
@@ -27272,43 +27191,27 @@
|
|
27272
27191
|
_this.altAudio = false;
|
27273
27192
|
_this.audioOnly = false;
|
27274
27193
|
_this.fragPlaying = null;
|
27194
|
+
_this.onvplaying = null;
|
27195
|
+
_this.onvseeked = null;
|
27275
27196
|
_this.fragLastKbps = 0;
|
27276
27197
|
_this.couldBacktrack = false;
|
27277
27198
|
_this.backtrackFragment = null;
|
27278
27199
|
_this.audioCodecSwitch = false;
|
27279
27200
|
_this.videoBuffer = null;
|
27280
|
-
_this.
|
27281
|
-
// tick to speed up FRAG_CHANGED triggering
|
27282
|
-
_this.tick();
|
27283
|
-
};
|
27284
|
-
_this.onMediaSeeked = function () {
|
27285
|
-
var media = _this.media;
|
27286
|
-
var currentTime = media ? media.currentTime : null;
|
27287
|
-
if (isFiniteNumber(currentTime)) {
|
27288
|
-
_this.log("Media seeked to " + currentTime.toFixed(3));
|
27289
|
-
}
|
27290
|
-
|
27291
|
-
// If seeked was issued before buffer was appended do not tick immediately
|
27292
|
-
var bufferInfo = _this.getMainFwdBufferInfo();
|
27293
|
-
if (bufferInfo === null || bufferInfo.len === 0) {
|
27294
|
-
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27295
|
-
return;
|
27296
|
-
}
|
27297
|
-
|
27298
|
-
// tick to speed up FRAG_CHANGED triggering
|
27299
|
-
_this.tick();
|
27300
|
-
};
|
27301
|
-
_this.registerListeners();
|
27201
|
+
_this._registerListeners();
|
27302
27202
|
return _this;
|
27303
27203
|
}
|
27304
27204
|
var _proto = StreamController.prototype;
|
27305
|
-
_proto.
|
27306
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
27205
|
+
_proto._registerListeners = function _registerListeners() {
|
27307
27206
|
var hls = this.hls;
|
27207
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27208
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27209
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
27308
27210
|
hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27309
27211
|
hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
|
27310
27212
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27311
27213
|
hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27214
|
+
hls.on(Events.ERROR, this.onError, this);
|
27312
27215
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27313
27216
|
hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27314
27217
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27316,12 +27219,15 @@
|
|
27316
27219
|
hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
|
27317
27220
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27318
27221
|
};
|
27319
|
-
_proto.
|
27320
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
27222
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
27321
27223
|
var hls = this.hls;
|
27224
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27225
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27226
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
27322
27227
|
hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27323
27228
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27324
27229
|
hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27230
|
+
hls.off(Events.ERROR, this.onError, this);
|
27325
27231
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27326
27232
|
hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27327
27233
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27330,9 +27236,7 @@
|
|
27330
27236
|
hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27331
27237
|
};
|
27332
27238
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
27333
|
-
|
27334
|
-
this.onMediaPlaying = this.onMediaSeeked = null;
|
27335
|
-
this.unregisterListeners();
|
27239
|
+
this._unregisterListeners();
|
27336
27240
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
27337
27241
|
};
|
27338
27242
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -27647,15 +27551,18 @@
|
|
27647
27551
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
27648
27552
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
27649
27553
|
var media = data.media;
|
27650
|
-
|
27651
|
-
|
27554
|
+
this.onvplaying = this.onMediaPlaying.bind(this);
|
27555
|
+
this.onvseeked = this.onMediaSeeked.bind(this);
|
27556
|
+
media.addEventListener('playing', this.onvplaying);
|
27557
|
+
media.addEventListener('seeked', this.onvseeked);
|
27652
27558
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
27653
27559
|
};
|
27654
27560
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
27655
27561
|
var media = this.media;
|
27656
|
-
if (media) {
|
27657
|
-
media.removeEventListener('playing', this.
|
27658
|
-
media.removeEventListener('seeked', this.
|
27562
|
+
if (media && this.onvplaying && this.onvseeked) {
|
27563
|
+
media.removeEventListener('playing', this.onvplaying);
|
27564
|
+
media.removeEventListener('seeked', this.onvseeked);
|
27565
|
+
this.onvplaying = this.onvseeked = null;
|
27659
27566
|
this.videoBuffer = null;
|
27660
27567
|
}
|
27661
27568
|
this.fragPlaying = null;
|
@@ -27665,6 +27572,27 @@
|
|
27665
27572
|
}
|
27666
27573
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
27667
27574
|
};
|
27575
|
+
_proto.onMediaPlaying = function onMediaPlaying() {
|
27576
|
+
// tick to speed up FRAG_CHANGED triggering
|
27577
|
+
this.tick();
|
27578
|
+
};
|
27579
|
+
_proto.onMediaSeeked = function onMediaSeeked() {
|
27580
|
+
var media = this.media;
|
27581
|
+
var currentTime = media ? media.currentTime : null;
|
27582
|
+
if (isFiniteNumber(currentTime)) {
|
27583
|
+
this.log("Media seeked to " + currentTime.toFixed(3));
|
27584
|
+
}
|
27585
|
+
|
27586
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
27587
|
+
var bufferInfo = this.getMainFwdBufferInfo();
|
27588
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
27589
|
+
this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27590
|
+
return;
|
27591
|
+
}
|
27592
|
+
|
27593
|
+
// tick to speed up FRAG_CHANGED triggering
|
27594
|
+
this.tick();
|
27595
|
+
};
|
27668
27596
|
_proto.onManifestLoading = function onManifestLoading() {
|
27669
27597
|
// reset buffer on manifest loading
|
27670
27598
|
this.log('Trigger BUFFER_RESET');
|
@@ -28411,10 +28339,6 @@
|
|
28411
28339
|
* The configuration object provided on player instantiation.
|
28412
28340
|
*/
|
28413
28341
|
this.userConfig = void 0;
|
28414
|
-
/**
|
28415
|
-
* The logger functions used by this player instance, configured on player instantiation.
|
28416
|
-
*/
|
28417
|
-
this.logger = void 0;
|
28418
28342
|
this.coreComponents = void 0;
|
28419
28343
|
this.networkControllers = void 0;
|
28420
28344
|
this.started = false;
|
@@ -28434,11 +28358,11 @@
|
|
28434
28358
|
this._media = null;
|
28435
28359
|
this.url = null;
|
28436
28360
|
this.triggeringException = void 0;
|
28437
|
-
|
28438
|
-
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig
|
28361
|
+
enableLogs(userConfig.debug || false, 'Hls instance');
|
28362
|
+
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
|
28439
28363
|
this.userConfig = userConfig;
|
28440
28364
|
if (config.progressive) {
|
28441
|
-
enableStreamingMode(config
|
28365
|
+
enableStreamingMode(config);
|
28442
28366
|
}
|
28443
28367
|
|
28444
28368
|
// core controllers and network loaders
|
@@ -28546,7 +28470,7 @@
|
|
28546
28470
|
try {
|
28547
28471
|
return this.emit(event, event, eventObject);
|
28548
28472
|
} catch (error) {
|
28549
|
-
|
28473
|
+
logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
28550
28474
|
// Prevent recursion in error event handlers that throw #5497
|
28551
28475
|
if (!this.triggeringException) {
|
28552
28476
|
this.triggeringException = true;
|
@@ -28572,7 +28496,7 @@
|
|
28572
28496
|
* Dispose of the instance
|
28573
28497
|
*/;
|
28574
28498
|
_proto.destroy = function destroy() {
|
28575
|
-
|
28499
|
+
logger.log('destroy');
|
28576
28500
|
this.trigger(Events.DESTROYING, undefined);
|
28577
28501
|
this.detachMedia();
|
28578
28502
|
this.removeAllListeners();
|
@@ -28597,7 +28521,7 @@
|
|
28597
28521
|
* Attaches Hls.js to a media element
|
28598
28522
|
*/;
|
28599
28523
|
_proto.attachMedia = function attachMedia(media) {
|
28600
|
-
|
28524
|
+
logger.log('attachMedia');
|
28601
28525
|
this._media = media;
|
28602
28526
|
this.trigger(Events.MEDIA_ATTACHING, {
|
28603
28527
|
media: media
|
@@ -28608,7 +28532,7 @@
|
|
28608
28532
|
* Detach Hls.js from the media
|
28609
28533
|
*/;
|
28610
28534
|
_proto.detachMedia = function detachMedia() {
|
28611
|
-
|
28535
|
+
logger.log('detachMedia');
|
28612
28536
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
28613
28537
|
this._media = null;
|
28614
28538
|
}
|
@@ -28625,7 +28549,7 @@
|
|
28625
28549
|
});
|
28626
28550
|
this._autoLevelCapping = -1;
|
28627
28551
|
this._maxHdcpLevel = null;
|
28628
|
-
|
28552
|
+
logger.log("loadSource:" + loadingSource);
|
28629
28553
|
if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
|
28630
28554
|
this.detachMedia();
|
28631
28555
|
this.attachMedia(media);
|
@@ -28647,7 +28571,7 @@
|
|
28647
28571
|
if (startPosition === void 0) {
|
28648
28572
|
startPosition = -1;
|
28649
28573
|
}
|
28650
|
-
|
28574
|
+
logger.log("startLoad(" + startPosition + ")");
|
28651
28575
|
this.started = true;
|
28652
28576
|
this.networkControllers.forEach(function (controller) {
|
28653
28577
|
controller.startLoad(startPosition);
|
@@ -28658,7 +28582,7 @@
|
|
28658
28582
|
* Stop loading of any stream data.
|
28659
28583
|
*/;
|
28660
28584
|
_proto.stopLoad = function stopLoad() {
|
28661
|
-
|
28585
|
+
logger.log('stopLoad');
|
28662
28586
|
this.started = false;
|
28663
28587
|
this.networkControllers.forEach(function (controller) {
|
28664
28588
|
controller.stopLoad();
|
@@ -28694,7 +28618,7 @@
|
|
28694
28618
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
28695
28619
|
*/;
|
28696
28620
|
_proto.swapAudioCodec = function swapAudioCodec() {
|
28697
|
-
|
28621
|
+
logger.log('swapAudioCodec');
|
28698
28622
|
this.streamController.swapAudioCodec();
|
28699
28623
|
}
|
28700
28624
|
|
@@ -28705,7 +28629,7 @@
|
|
28705
28629
|
* Automatic recovery of media-errors by this process is configurable.
|
28706
28630
|
*/;
|
28707
28631
|
_proto.recoverMediaError = function recoverMediaError() {
|
28708
|
-
|
28632
|
+
logger.log('recoverMediaError');
|
28709
28633
|
var media = this._media;
|
28710
28634
|
this.detachMedia();
|
28711
28635
|
if (media) {
|
@@ -28760,7 +28684,7 @@
|
|
28760
28684
|
* Set quality level index immediately. This will flush the current buffer to replace the quality asap. That means playback will interrupt at least shortly to re-buffer and re-sync eventually. Set to -1 for automatic level selection.
|
28761
28685
|
*/,
|
28762
28686
|
set: function set(newLevel) {
|
28763
|
-
|
28687
|
+
logger.log("set currentLevel:" + newLevel);
|
28764
28688
|
this.levelController.manualLevel = newLevel;
|
28765
28689
|
this.streamController.immediateLevelSwitch();
|
28766
28690
|
}
|
@@ -28781,7 +28705,7 @@
|
|
28781
28705
|
* @param newLevel - Pass -1 for automatic level selection
|
28782
28706
|
*/,
|
28783
28707
|
set: function set(newLevel) {
|
28784
|
-
|
28708
|
+
logger.log("set nextLevel:" + newLevel);
|
28785
28709
|
this.levelController.manualLevel = newLevel;
|
28786
28710
|
this.streamController.nextLevelSwitch();
|
28787
28711
|
}
|
@@ -28802,7 +28726,7 @@
|
|
28802
28726
|
* @param newLevel - Pass -1 for automatic level selection
|
28803
28727
|
*/,
|
28804
28728
|
set: function set(newLevel) {
|
28805
|
-
|
28729
|
+
logger.log("set loadLevel:" + newLevel);
|
28806
28730
|
this.levelController.manualLevel = newLevel;
|
28807
28731
|
}
|
28808
28732
|
|
@@ -28837,7 +28761,7 @@
|
|
28837
28761
|
* Sets "first-level", see getter.
|
28838
28762
|
*/,
|
28839
28763
|
set: function set(newLevel) {
|
28840
|
-
|
28764
|
+
logger.log("set firstLevel:" + newLevel);
|
28841
28765
|
this.levelController.firstLevel = newLevel;
|
28842
28766
|
}
|
28843
28767
|
|
@@ -28864,7 +28788,7 @@
|
|
28864
28788
|
* (determined from download of first segment)
|
28865
28789
|
*/,
|
28866
28790
|
set: function set(newLevel) {
|
28867
|
-
|
28791
|
+
logger.log("set startLevel:" + newLevel);
|
28868
28792
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
28869
28793
|
if (newLevel !== -1) {
|
28870
28794
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -28917,7 +28841,7 @@
|
|
28917
28841
|
*/
|
28918
28842
|
function set(newLevel) {
|
28919
28843
|
if (this._autoLevelCapping !== newLevel) {
|
28920
|
-
|
28844
|
+
logger.log("set autoLevelCapping:" + newLevel);
|
28921
28845
|
this._autoLevelCapping = newLevel;
|
28922
28846
|
this.levelController.checkMaxAutoUpdated();
|
28923
28847
|
}
|
@@ -29242,7 +29166,7 @@
|
|
29242
29166
|
* Get the video-dev/hls.js package version.
|
29243
29167
|
*/
|
29244
29168
|
function get() {
|
29245
|
-
return "1.5.2
|
29169
|
+
return "1.5.2";
|
29246
29170
|
}
|
29247
29171
|
}, {
|
29248
29172
|
key: "Events",
|