hls.js 1.5.4 → 1.5.5-0.canary.9977
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/README.md +1 -0
- package/dist/hls-demo.js +10 -0
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +1930 -1095
- package/dist/hls.js.d.ts +63 -50
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +1609 -778
- 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 +1363 -542
- 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 +1635 -815
- 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 +18 -18
- package/src/config.ts +3 -2
- package/src/controller/abr-controller.ts +21 -20
- package/src/controller/audio-stream-controller.ts +15 -16
- 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 +56 -29
- package/src/controller/buffer-controller.ts +11 -11
- package/src/controller/cap-level-controller.ts +1 -2
- package/src/controller/cmcd-controller.ts +25 -3
- package/src/controller/content-steering-controller.ts +8 -6
- package/src/controller/eme-controller.ts +9 -22
- package/src/controller/error-controller.ts +6 -8
- package/src/controller/fps-controller.ts +2 -3
- package/src/controller/gap-controller.ts +43 -16
- package/src/controller/latency-controller.ts +9 -11
- package/src/controller/level-controller.ts +5 -17
- package/src/controller/stream-controller.ts +25 -32
- package/src/controller/subtitle-stream-controller.ts +13 -14
- package/src/controller/subtitle-track-controller.ts +5 -3
- package/src/controller/timeline-controller.ts +23 -30
- package/src/crypt/aes-crypto.ts +21 -2
- package/src/crypt/decrypter-aes-mode.ts +4 -0
- package/src/crypt/decrypter.ts +32 -18
- package/src/crypt/fast-aes-key.ts +24 -5
- package/src/demux/audio/adts.ts +9 -4
- package/src/demux/sample-aes.ts +2 -0
- package/src/demux/transmuxer-interface.ts +4 -12
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +16 -3
- package/src/demux/tsdemuxer.ts +63 -37
- package/src/demux/video/avc-video-parser.ts +208 -119
- package/src/demux/video/base-video-parser.ts +134 -2
- package/src/demux/video/exp-golomb.ts +0 -208
- package/src/demux/video/hevc-video-parser.ts +746 -0
- package/src/events.ts +7 -0
- package/src/hls.ts +42 -34
- package/src/loader/fragment-loader.ts +9 -2
- package/src/loader/key-loader.ts +2 -0
- package/src/loader/level-key.ts +10 -9
- package/src/remux/mp4-generator.ts +196 -1
- package/src/remux/mp4-remuxer.ts +23 -7
- package/src/task-loop.ts +5 -2
- package/src/types/component-api.ts +2 -0
- package/src/types/demuxer.ts +3 -0
- package/src/types/events.ts +4 -0
- package/src/utils/codecs.ts +33 -4
- package/src/utils/encryption-methods-util.ts +21 -0
- package/src/utils/logger.ts +53 -24
package/dist/hls.js
CHANGED
@@ -5,6 +5,21 @@
|
|
5
5
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Hls = factory());
|
6
6
|
})(this, (function () { 'use strict';
|
7
7
|
|
8
|
+
function _construct(t, e, r) {
|
9
|
+
if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
|
10
|
+
var o = [null];
|
11
|
+
o.push.apply(o, e);
|
12
|
+
var p = new (t.bind.apply(t, o))();
|
13
|
+
return r && _setPrototypeOf(p, r.prototype), p;
|
14
|
+
}
|
15
|
+
function _isNativeReflectConstruct() {
|
16
|
+
try {
|
17
|
+
var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
18
|
+
} catch (t) {}
|
19
|
+
return (_isNativeReflectConstruct = function () {
|
20
|
+
return !!t;
|
21
|
+
})();
|
22
|
+
}
|
8
23
|
function ownKeys(e, r) {
|
9
24
|
var t = Object.keys(e);
|
10
25
|
if (Object.getOwnPropertySymbols) {
|
@@ -103,32 +118,6 @@
|
|
103
118
|
};
|
104
119
|
return _setPrototypeOf(o, p);
|
105
120
|
}
|
106
|
-
function _isNativeReflectConstruct() {
|
107
|
-
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
108
|
-
if (Reflect.construct.sham) return false;
|
109
|
-
if (typeof Proxy === "function") return true;
|
110
|
-
try {
|
111
|
-
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
112
|
-
return true;
|
113
|
-
} catch (e) {
|
114
|
-
return false;
|
115
|
-
}
|
116
|
-
}
|
117
|
-
function _construct(Parent, args, Class) {
|
118
|
-
if (_isNativeReflectConstruct()) {
|
119
|
-
_construct = Reflect.construct.bind();
|
120
|
-
} else {
|
121
|
-
_construct = function _construct(Parent, args, Class) {
|
122
|
-
var a = [null];
|
123
|
-
a.push.apply(a, args);
|
124
|
-
var Constructor = Function.bind.apply(Parent, a);
|
125
|
-
var instance = new Constructor();
|
126
|
-
if (Class) _setPrototypeOf(instance, Class.prototype);
|
127
|
-
return instance;
|
128
|
-
};
|
129
|
-
}
|
130
|
-
return _construct.apply(null, arguments);
|
131
|
-
}
|
132
121
|
function _isNativeFunction(fn) {
|
133
122
|
try {
|
134
123
|
return Function.toString.call(fn).indexOf("[native code]") !== -1;
|
@@ -394,6 +383,7 @@
|
|
394
383
|
Events["MEDIA_ATTACHED"] = "hlsMediaAttached";
|
395
384
|
Events["MEDIA_DETACHING"] = "hlsMediaDetaching";
|
396
385
|
Events["MEDIA_DETACHED"] = "hlsMediaDetached";
|
386
|
+
Events["MEDIA_ENDED"] = "hlsMediaEnded";
|
397
387
|
Events["BUFFER_RESET"] = "hlsBufferReset";
|
398
388
|
Events["BUFFER_CODECS"] = "hlsBufferCodecs";
|
399
389
|
Events["BUFFER_CREATED"] = "hlsBufferCreated";
|
@@ -507,6 +497,21 @@
|
|
507
497
|
return ErrorDetails;
|
508
498
|
}({});
|
509
499
|
|
500
|
+
var Logger = function Logger(label, logger) {
|
501
|
+
this.trace = void 0;
|
502
|
+
this.debug = void 0;
|
503
|
+
this.log = void 0;
|
504
|
+
this.warn = void 0;
|
505
|
+
this.info = void 0;
|
506
|
+
this.error = void 0;
|
507
|
+
var lb = "[" + label + "]:";
|
508
|
+
this.trace = noop;
|
509
|
+
this.debug = logger.debug.bind(null, lb);
|
510
|
+
this.log = logger.log.bind(null, lb);
|
511
|
+
this.warn = logger.warn.bind(null, lb);
|
512
|
+
this.info = logger.info.bind(null, lb);
|
513
|
+
this.error = logger.error.bind(null, lb);
|
514
|
+
};
|
510
515
|
var noop = function noop() {};
|
511
516
|
var fakeLogger = {
|
512
517
|
trace: noop,
|
@@ -516,7 +521,9 @@
|
|
516
521
|
info: noop,
|
517
522
|
error: noop
|
518
523
|
};
|
519
|
-
|
524
|
+
function createLogger() {
|
525
|
+
return _extends({}, fakeLogger);
|
526
|
+
}
|
520
527
|
|
521
528
|
// let lastCallTime;
|
522
529
|
// function formatMsgWithTimeInfo(type, msg) {
|
@@ -527,38 +534,36 @@
|
|
527
534
|
// return msg;
|
528
535
|
// }
|
529
536
|
|
530
|
-
function consolePrintFn(type) {
|
537
|
+
function consolePrintFn(type, id) {
|
531
538
|
var func = self.console[type];
|
532
|
-
|
533
|
-
return func.bind(self.console, "[" + type + "] >");
|
534
|
-
}
|
535
|
-
return noop;
|
539
|
+
return func ? func.bind(self.console, (id ? '[' + id + '] ' : '') + "[" + type + "] >") : noop;
|
536
540
|
}
|
537
|
-
function
|
538
|
-
|
539
|
-
functions[_key - 1] = arguments[_key];
|
540
|
-
}
|
541
|
-
functions.forEach(function (type) {
|
542
|
-
exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);
|
543
|
-
});
|
541
|
+
function getLoggerFn(key, debugConfig, id) {
|
542
|
+
return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key, id);
|
544
543
|
}
|
545
|
-
|
544
|
+
var exportedLogger = createLogger();
|
545
|
+
function enableLogs(debugConfig, context, id) {
|
546
546
|
// check that console is available
|
547
|
+
var newLogger = createLogger();
|
547
548
|
if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
|
548
|
-
|
549
|
+
var keys = [
|
549
550
|
// Remove out from list here to hard-disable a log-level
|
550
551
|
// 'trace',
|
551
|
-
'debug', 'log', 'info', 'warn', 'error'
|
552
|
+
'debug', 'log', 'info', 'warn', 'error'];
|
553
|
+
keys.forEach(function (key) {
|
554
|
+
newLogger[key] = getLoggerFn(key, debugConfig, id);
|
555
|
+
});
|
552
556
|
// Some browsers don't allow to use bind on console object anyway
|
553
557
|
// fallback to default if needed
|
554
558
|
try {
|
555
|
-
|
559
|
+
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.5-0.canary.9977");
|
556
560
|
} catch (e) {
|
557
|
-
|
561
|
+
/* log fn threw an exception. All logger methods are no-ops. */
|
562
|
+
return createLogger();
|
558
563
|
}
|
559
|
-
} else {
|
560
|
-
exportedLogger = fakeLogger;
|
561
564
|
}
|
565
|
+
exportedLogger = newLogger;
|
566
|
+
return newLogger;
|
562
567
|
}
|
563
568
|
var logger = exportedLogger;
|
564
569
|
|
@@ -1253,6 +1258,26 @@
|
|
1253
1258
|
});
|
1254
1259
|
}
|
1255
1260
|
|
1261
|
+
var DecrypterAesMode = {
|
1262
|
+
cbc: 0,
|
1263
|
+
ctr: 1
|
1264
|
+
};
|
1265
|
+
|
1266
|
+
function isFullSegmentEncryption(method) {
|
1267
|
+
return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
|
1268
|
+
}
|
1269
|
+
function getAesModeFromFullSegmentMethod(method) {
|
1270
|
+
switch (method) {
|
1271
|
+
case 'AES-128':
|
1272
|
+
case 'AES-256':
|
1273
|
+
return DecrypterAesMode.cbc;
|
1274
|
+
case 'AES-256-CTR':
|
1275
|
+
return DecrypterAesMode.ctr;
|
1276
|
+
default:
|
1277
|
+
throw new Error("invalid full segment method " + method);
|
1278
|
+
}
|
1279
|
+
}
|
1280
|
+
|
1256
1281
|
/** returns `undefined` is `self` is missing, e.g. in node */
|
1257
1282
|
var optionalSelf = typeof self !== 'undefined' ? self : undefined;
|
1258
1283
|
|
@@ -2923,13 +2948,13 @@
|
|
2923
2948
|
this.keyFormatVersions = formatversions;
|
2924
2949
|
this.iv = iv;
|
2925
2950
|
this.encrypted = method ? method !== 'NONE' : false;
|
2926
|
-
this.isCommonEncryption = this.encrypted && method
|
2951
|
+
this.isCommonEncryption = this.encrypted && !isFullSegmentEncryption(method);
|
2927
2952
|
}
|
2928
2953
|
var _proto = LevelKey.prototype;
|
2929
2954
|
_proto.isSupported = function isSupported() {
|
2930
2955
|
// If it's Segment encryption or No encryption, just select that key system
|
2931
2956
|
if (this.method) {
|
2932
|
-
if (this.method
|
2957
|
+
if (isFullSegmentEncryption(this.method) || this.method === 'NONE') {
|
2933
2958
|
return true;
|
2934
2959
|
}
|
2935
2960
|
if (this.keyFormat === 'identity') {
|
@@ -2951,14 +2976,13 @@
|
|
2951
2976
|
if (!this.encrypted || !this.uri) {
|
2952
2977
|
return null;
|
2953
2978
|
}
|
2954
|
-
if (this.method
|
2979
|
+
if (isFullSegmentEncryption(this.method) && this.uri && !this.iv) {
|
2955
2980
|
if (typeof sn !== 'number') {
|
2956
2981
|
// We are fetching decryption data for a initialization segment
|
2957
|
-
// If the segment was encrypted with AES-128
|
2982
|
+
// If the segment was encrypted with AES-128/256
|
2958
2983
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
2959
|
-
|
2960
|
-
|
2961
|
-
}
|
2984
|
+
logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
|
2985
|
+
|
2962
2986
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
2963
2987
|
sn = 0;
|
2964
2988
|
}
|
@@ -3252,23 +3276,28 @@
|
|
3252
3276
|
if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
|
3253
3277
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
|
3254
3278
|
}
|
3255
|
-
|
3256
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3257
|
-
// some browsers will report that fLaC is supported then fail.
|
3258
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3259
3279
|
var codecsToCheck = {
|
3280
|
+
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3281
|
+
// some browsers will report that fLaC is supported then fail.
|
3282
|
+
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3260
3283
|
flac: ['flac', 'fLaC', 'FLAC'],
|
3261
|
-
opus: ['opus', 'Opus']
|
3284
|
+
opus: ['opus', 'Opus'],
|
3285
|
+
// Replace audio codec info if browser does not support mp4a.40.34,
|
3286
|
+
// and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
|
3287
|
+
'mp4a.40.34': ['mp3']
|
3262
3288
|
}[lowerCaseCodec];
|
3263
3289
|
for (var i = 0; i < codecsToCheck.length; i++) {
|
3290
|
+
var _getMediaSource;
|
3264
3291
|
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
|
3265
3292
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
3266
3293
|
return codecsToCheck[i];
|
3294
|
+
} else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
|
3295
|
+
return '';
|
3267
3296
|
}
|
3268
3297
|
}
|
3269
3298
|
return lowerCaseCodec;
|
3270
3299
|
}
|
3271
|
-
var AUDIO_CODEC_REGEXP = /flac|opus/i;
|
3300
|
+
var AUDIO_CODEC_REGEXP = /flac|opus|mp4a\.40\.34/i;
|
3272
3301
|
function getCodecCompatibleName(codec, preferManagedMediaSource) {
|
3273
3302
|
if (preferManagedMediaSource === void 0) {
|
3274
3303
|
preferManagedMediaSource = true;
|
@@ -3296,6 +3325,18 @@
|
|
3296
3325
|
}
|
3297
3326
|
return codec;
|
3298
3327
|
}
|
3328
|
+
function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
|
3329
|
+
var MediaSource = getMediaSource(preferManagedMediaSource) || {
|
3330
|
+
isTypeSupported: function isTypeSupported() {
|
3331
|
+
return false;
|
3332
|
+
}
|
3333
|
+
};
|
3334
|
+
return {
|
3335
|
+
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
3336
|
+
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
3337
|
+
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
3338
|
+
};
|
3339
|
+
}
|
3299
3340
|
|
3300
3341
|
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;
|
3301
3342
|
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
|
@@ -4959,8 +5000,43 @@
|
|
4959
5000
|
this.currentTime = 0;
|
4960
5001
|
this.stallCount = 0;
|
4961
5002
|
this._latency = null;
|
4962
|
-
this.
|
4963
|
-
|
5003
|
+
this.onTimeupdate = function () {
|
5004
|
+
var media = _this.media,
|
5005
|
+
levelDetails = _this.levelDetails;
|
5006
|
+
if (!media || !levelDetails) {
|
5007
|
+
return;
|
5008
|
+
}
|
5009
|
+
_this.currentTime = media.currentTime;
|
5010
|
+
var latency = _this.computeLatency();
|
5011
|
+
if (latency === null) {
|
5012
|
+
return;
|
5013
|
+
}
|
5014
|
+
_this._latency = latency;
|
5015
|
+
|
5016
|
+
// Adapt playbackRate to meet target latency in low-latency mode
|
5017
|
+
var _this$config = _this.config,
|
5018
|
+
lowLatencyMode = _this$config.lowLatencyMode,
|
5019
|
+
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5020
|
+
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5021
|
+
return;
|
5022
|
+
}
|
5023
|
+
var targetLatency = _this.targetLatency;
|
5024
|
+
if (targetLatency === null) {
|
5025
|
+
return;
|
5026
|
+
}
|
5027
|
+
var distanceFromTarget = latency - targetLatency;
|
5028
|
+
// Only adjust playbackRate when within one target duration of targetLatency
|
5029
|
+
// and more than one second from under-buffering.
|
5030
|
+
// Playback further than one target duration from target can be considered DVR playback.
|
5031
|
+
var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
|
5032
|
+
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5033
|
+
if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
|
5034
|
+
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5035
|
+
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
|
5036
|
+
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5037
|
+
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5038
|
+
media.playbackRate = 1;
|
5039
|
+
}
|
4964
5040
|
};
|
4965
5041
|
this.hls = hls;
|
4966
5042
|
this.config = hls.config;
|
@@ -4972,7 +5048,7 @@
|
|
4972
5048
|
this.onMediaDetaching();
|
4973
5049
|
this.levelDetails = null;
|
4974
5050
|
// @ts-ignore
|
4975
|
-
this.hls =
|
5051
|
+
this.hls = null;
|
4976
5052
|
};
|
4977
5053
|
_proto.registerListeners = function registerListeners() {
|
4978
5054
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -4990,11 +5066,11 @@
|
|
4990
5066
|
};
|
4991
5067
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
4992
5068
|
this.media = data.media;
|
4993
|
-
this.media.addEventListener('timeupdate', this.
|
5069
|
+
this.media.addEventListener('timeupdate', this.onTimeupdate);
|
4994
5070
|
};
|
4995
5071
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
4996
5072
|
if (this.media) {
|
4997
|
-
this.media.removeEventListener('timeupdate', this.
|
5073
|
+
this.media.removeEventListener('timeupdate', this.onTimeupdate);
|
4998
5074
|
this.media = null;
|
4999
5075
|
}
|
5000
5076
|
};
|
@@ -5007,10 +5083,10 @@
|
|
5007
5083
|
var details = _ref.details;
|
5008
5084
|
this.levelDetails = details;
|
5009
5085
|
if (details.advanced) {
|
5010
|
-
this.
|
5086
|
+
this.onTimeupdate();
|
5011
5087
|
}
|
5012
5088
|
if (!details.live && this.media) {
|
5013
|
-
this.media.removeEventListener('timeupdate', this.
|
5089
|
+
this.media.removeEventListener('timeupdate', this.onTimeupdate);
|
5014
5090
|
}
|
5015
5091
|
};
|
5016
5092
|
_proto.onError = function onError(event, data) {
|
@@ -5020,45 +5096,7 @@
|
|
5020
5096
|
}
|
5021
5097
|
this.stallCount++;
|
5022
5098
|
if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
|
5023
|
-
logger.warn('[
|
5024
|
-
}
|
5025
|
-
};
|
5026
|
-
_proto.timeupdate = function timeupdate() {
|
5027
|
-
var media = this.media,
|
5028
|
-
levelDetails = this.levelDetails;
|
5029
|
-
if (!media || !levelDetails) {
|
5030
|
-
return;
|
5031
|
-
}
|
5032
|
-
this.currentTime = media.currentTime;
|
5033
|
-
var latency = this.computeLatency();
|
5034
|
-
if (latency === null) {
|
5035
|
-
return;
|
5036
|
-
}
|
5037
|
-
this._latency = latency;
|
5038
|
-
|
5039
|
-
// Adapt playbackRate to meet target latency in low-latency mode
|
5040
|
-
var _this$config = this.config,
|
5041
|
-
lowLatencyMode = _this$config.lowLatencyMode,
|
5042
|
-
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5043
|
-
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5044
|
-
return;
|
5045
|
-
}
|
5046
|
-
var targetLatency = this.targetLatency;
|
5047
|
-
if (targetLatency === null) {
|
5048
|
-
return;
|
5049
|
-
}
|
5050
|
-
var distanceFromTarget = latency - targetLatency;
|
5051
|
-
// Only adjust playbackRate when within one target duration of targetLatency
|
5052
|
-
// and more than one second from under-buffering.
|
5053
|
-
// Playback further than one target duration from target can be considered DVR playback.
|
5054
|
-
var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
|
5055
|
-
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5056
|
-
if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
|
5057
|
-
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5058
|
-
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
|
5059
|
-
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5060
|
-
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5061
|
-
media.playbackRate = 1;
|
5099
|
+
this.hls.logger.warn('[latency-controller]: Stall detected, adjusting target latency');
|
5062
5100
|
}
|
5063
5101
|
};
|
5064
5102
|
_proto.estimateLiveEdge = function estimateLiveEdge() {
|
@@ -5966,19 +6004,17 @@
|
|
5966
6004
|
MoveAllAlternatesMatchingHDCP: 2,
|
5967
6005
|
SwitchToSDR: 4
|
5968
6006
|
}; // Reserved for future use
|
5969
|
-
var ErrorController = /*#__PURE__*/function () {
|
6007
|
+
var ErrorController = /*#__PURE__*/function (_Logger) {
|
6008
|
+
_inheritsLoose(ErrorController, _Logger);
|
5970
6009
|
function ErrorController(hls) {
|
5971
|
-
|
5972
|
-
this.
|
5973
|
-
|
5974
|
-
|
5975
|
-
|
5976
|
-
|
5977
|
-
|
5978
|
-
|
5979
|
-
this.warn = logger.warn.bind(logger, "[warning]:");
|
5980
|
-
this.error = logger.error.bind(logger, "[error]:");
|
5981
|
-
this.registerListeners();
|
6010
|
+
var _this;
|
6011
|
+
_this = _Logger.call(this, 'error-controller', hls.logger) || this;
|
6012
|
+
_this.hls = void 0;
|
6013
|
+
_this.playlistError = 0;
|
6014
|
+
_this.penalizedRenditions = {};
|
6015
|
+
_this.hls = hls;
|
6016
|
+
_this.registerListeners();
|
6017
|
+
return _this;
|
5982
6018
|
}
|
5983
6019
|
var _proto = ErrorController.prototype;
|
5984
6020
|
_proto.registerListeners = function registerListeners() {
|
@@ -6334,19 +6370,19 @@
|
|
6334
6370
|
}
|
6335
6371
|
};
|
6336
6372
|
return ErrorController;
|
6337
|
-
}();
|
6373
|
+
}(Logger);
|
6338
6374
|
|
6339
|
-
var BasePlaylistController = /*#__PURE__*/function () {
|
6375
|
+
var BasePlaylistController = /*#__PURE__*/function (_Logger) {
|
6376
|
+
_inheritsLoose(BasePlaylistController, _Logger);
|
6340
6377
|
function BasePlaylistController(hls, logPrefix) {
|
6341
|
-
|
6342
|
-
this.
|
6343
|
-
|
6344
|
-
|
6345
|
-
|
6346
|
-
|
6347
|
-
|
6348
|
-
|
6349
|
-
this.hls = hls;
|
6378
|
+
var _this;
|
6379
|
+
_this = _Logger.call(this, logPrefix, hls.logger) || this;
|
6380
|
+
_this.hls = void 0;
|
6381
|
+
_this.timer = -1;
|
6382
|
+
_this.requestScheduled = -1;
|
6383
|
+
_this.canLoad = false;
|
6384
|
+
_this.hls = hls;
|
6385
|
+
return _this;
|
6350
6386
|
}
|
6351
6387
|
var _proto = BasePlaylistController.prototype;
|
6352
6388
|
_proto.destroy = function destroy() {
|
@@ -6379,7 +6415,7 @@
|
|
6379
6415
|
try {
|
6380
6416
|
uri = new self.URL(attr.URI, previous.url).href;
|
6381
6417
|
} catch (error) {
|
6382
|
-
|
6418
|
+
this.warn("Could not construct new URL for Rendition Report: " + error);
|
6383
6419
|
uri = attr.URI || '';
|
6384
6420
|
}
|
6385
6421
|
// Use exact match. Otherwise, the last partial match, if any, will be used
|
@@ -6418,7 +6454,7 @@
|
|
6418
6454
|
return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
|
6419
6455
|
};
|
6420
6456
|
_proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
|
6421
|
-
var
|
6457
|
+
var _this2 = this;
|
6422
6458
|
var details = data.details,
|
6423
6459
|
stats = data.stats;
|
6424
6460
|
|
@@ -6523,7 +6559,7 @@
|
|
6523
6559
|
// );
|
6524
6560
|
|
6525
6561
|
this.timer = self.setTimeout(function () {
|
6526
|
-
return
|
6562
|
+
return _this2.loadPlaylist(deliveryDirectives);
|
6527
6563
|
}, estimatedTimeUntilUpdate);
|
6528
6564
|
} else {
|
6529
6565
|
this.clearTimer();
|
@@ -6539,7 +6575,7 @@
|
|
6539
6575
|
return new HlsUrlParameters(msn, part, skip);
|
6540
6576
|
};
|
6541
6577
|
_proto.checkRetry = function checkRetry(errorEvent) {
|
6542
|
-
var
|
6578
|
+
var _this3 = this;
|
6543
6579
|
var errorDetails = errorEvent.details;
|
6544
6580
|
var isTimeout = isTimeoutError(errorEvent);
|
6545
6581
|
var errorAction = errorEvent.errorAction;
|
@@ -6563,7 +6599,7 @@
|
|
6563
6599
|
var delay = getRetryDelay(retryConfig, retryCount);
|
6564
6600
|
// Schedule level/track reload
|
6565
6601
|
this.timer = self.setTimeout(function () {
|
6566
|
-
return
|
6602
|
+
return _this3.loadPlaylist();
|
6567
6603
|
}, delay);
|
6568
6604
|
this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
|
6569
6605
|
}
|
@@ -6574,7 +6610,7 @@
|
|
6574
6610
|
return retry;
|
6575
6611
|
};
|
6576
6612
|
return BasePlaylistController;
|
6577
|
-
}();
|
6613
|
+
}(Logger);
|
6578
6614
|
|
6579
6615
|
/*
|
6580
6616
|
* compute an Exponential Weighted moving average
|
@@ -7176,30 +7212,33 @@
|
|
7176
7212
|
return -1;
|
7177
7213
|
}
|
7178
7214
|
|
7179
|
-
var AbrController = /*#__PURE__*/function () {
|
7215
|
+
var AbrController = /*#__PURE__*/function (_Logger) {
|
7216
|
+
_inheritsLoose(AbrController, _Logger);
|
7180
7217
|
function AbrController(_hls) {
|
7181
|
-
var _this
|
7182
|
-
this.
|
7183
|
-
|
7184
|
-
|
7185
|
-
|
7186
|
-
|
7187
|
-
|
7188
|
-
|
7189
|
-
|
7190
|
-
|
7191
|
-
|
7192
|
-
|
7193
|
-
|
7194
|
-
|
7218
|
+
var _this;
|
7219
|
+
_this = _Logger.call(this, 'abr', _hls.logger) || this;
|
7220
|
+
_this.hls = void 0;
|
7221
|
+
_this.lastLevelLoadSec = 0;
|
7222
|
+
_this.lastLoadedFragLevel = -1;
|
7223
|
+
_this.firstSelection = -1;
|
7224
|
+
_this._nextAutoLevel = -1;
|
7225
|
+
_this.nextAutoLevelKey = '';
|
7226
|
+
_this.audioTracksByGroup = null;
|
7227
|
+
_this.codecTiers = null;
|
7228
|
+
_this.timer = -1;
|
7229
|
+
_this.fragCurrent = null;
|
7230
|
+
_this.partCurrent = null;
|
7231
|
+
_this.bitrateTestDelay = 0;
|
7232
|
+
_this.bwEstimator = void 0;
|
7195
7233
|
/*
|
7196
7234
|
This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
|
7197
7235
|
quickly enough to prevent underbuffering
|
7198
7236
|
*/
|
7199
|
-
|
7200
|
-
var
|
7201
|
-
|
7202
|
-
|
7237
|
+
_this._abandonRulesCheck = function () {
|
7238
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
7239
|
+
frag = _assertThisInitialize.fragCurrent,
|
7240
|
+
part = _assertThisInitialize.partCurrent,
|
7241
|
+
hls = _assertThisInitialize.hls;
|
7203
7242
|
var autoLevelEnabled = hls.autoLevelEnabled,
|
7204
7243
|
media = hls.media;
|
7205
7244
|
if (!frag || !media) {
|
@@ -7288,21 +7327,22 @@
|
|
7288
7327
|
_this.resetEstimator(nextLoadLevelBitrate);
|
7289
7328
|
}
|
7290
7329
|
_this.clearTimer();
|
7291
|
-
|
7330
|
+
_this.warn("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");
|
7292
7331
|
hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
|
7293
7332
|
frag: frag,
|
7294
7333
|
part: part,
|
7295
7334
|
stats: stats
|
7296
7335
|
});
|
7297
7336
|
};
|
7298
|
-
|
7299
|
-
|
7300
|
-
|
7337
|
+
_this.hls = _hls;
|
7338
|
+
_this.bwEstimator = _this.initEstimator();
|
7339
|
+
_this.registerListeners();
|
7340
|
+
return _this;
|
7301
7341
|
}
|
7302
7342
|
var _proto = AbrController.prototype;
|
7303
7343
|
_proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
|
7304
7344
|
if (abrEwmaDefaultEstimate) {
|
7305
|
-
|
7345
|
+
this.log("setting initial bwe to " + abrEwmaDefaultEstimate);
|
7306
7346
|
this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
|
7307
7347
|
}
|
7308
7348
|
this.firstSelection = -1;
|
@@ -7554,13 +7594,13 @@
|
|
7554
7594
|
// cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
|
7555
7595
|
var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
|
7556
7596
|
maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
|
7557
|
-
|
7597
|
+
this.info("bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
|
7558
7598
|
// don't use conservative factor on bitrate test
|
7559
7599
|
bwFactor = bwUpFactor = 1;
|
7560
7600
|
}
|
7561
7601
|
}
|
7562
7602
|
var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
|
7563
|
-
|
7603
|
+
this.info((bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
|
7564
7604
|
if (bestLevel > -1) {
|
7565
7605
|
return bestLevel;
|
7566
7606
|
}
|
@@ -7616,7 +7656,7 @@
|
|
7616
7656
|
currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
|
7617
7657
|
currentFrameRate = minFramerate;
|
7618
7658
|
currentBw = Math.max(currentBw, minBitrate);
|
7619
|
-
|
7659
|
+
this.log("picked start tier " + JSON.stringify(startTier));
|
7620
7660
|
} else {
|
7621
7661
|
currentCodecSet = level == null ? void 0 : level.codecSet;
|
7622
7662
|
currentVideoRange = level == null ? void 0 : level.videoRange;
|
@@ -7640,11 +7680,11 @@
|
|
7640
7680
|
var levels = _this2.hls.levels;
|
7641
7681
|
var index = levels.indexOf(levelInfo);
|
7642
7682
|
if (decodingInfo.error) {
|
7643
|
-
|
7683
|
+
_this2.warn("MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
|
7644
7684
|
} else if (!decodingInfo.supported) {
|
7645
|
-
|
7685
|
+
_this2.warn("Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
|
7646
7686
|
if (index > -1 && levels.length > 1) {
|
7647
|
-
|
7687
|
+
_this2.log("Removing unsupported level " + index);
|
7648
7688
|
_this2.hls.removeLevel(index);
|
7649
7689
|
}
|
7650
7690
|
}
|
@@ -7691,9 +7731,9 @@
|
|
7691
7731
|
var forcedAutoLevel = _this2.forcedAutoLevel;
|
7692
7732
|
if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
|
7693
7733
|
if (levelsSkipped.length) {
|
7694
|
-
|
7734
|
+
_this2.trace("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);
|
7695
7735
|
}
|
7696
|
-
|
7736
|
+
_this2.info("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);
|
7697
7737
|
}
|
7698
7738
|
if (firstSelection) {
|
7699
7739
|
_this2.firstSelection = i;
|
@@ -7727,7 +7767,7 @@
|
|
7727
7767
|
}
|
7728
7768
|
var firstLevel = this.hls.firstLevel;
|
7729
7769
|
var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
|
7730
|
-
|
7770
|
+
this.warn("Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
|
7731
7771
|
return clamped;
|
7732
7772
|
}
|
7733
7773
|
}, {
|
@@ -7780,7 +7820,7 @@
|
|
7780
7820
|
}
|
7781
7821
|
}]);
|
7782
7822
|
return AbrController;
|
7783
|
-
}();
|
7823
|
+
}(Logger);
|
7784
7824
|
|
7785
7825
|
/**
|
7786
7826
|
* @ignore
|
@@ -7811,13 +7851,17 @@
|
|
7811
7851
|
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
|
7812
7852
|
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
|
7813
7853
|
*/
|
7814
|
-
var TaskLoop = /*#__PURE__*/function () {
|
7815
|
-
|
7816
|
-
|
7817
|
-
|
7818
|
-
|
7819
|
-
|
7820
|
-
|
7854
|
+
var TaskLoop = /*#__PURE__*/function (_Logger) {
|
7855
|
+
_inheritsLoose(TaskLoop, _Logger);
|
7856
|
+
function TaskLoop(label, logger) {
|
7857
|
+
var _this;
|
7858
|
+
_this = _Logger.call(this, label, logger) || this;
|
7859
|
+
_this._boundTick = void 0;
|
7860
|
+
_this._tickTimer = null;
|
7861
|
+
_this._tickInterval = null;
|
7862
|
+
_this._tickCallCount = 0;
|
7863
|
+
_this._boundTick = _this.tick.bind(_assertThisInitialized(_this));
|
7864
|
+
return _this;
|
7821
7865
|
}
|
7822
7866
|
var _proto = TaskLoop.prototype;
|
7823
7867
|
_proto.destroy = function destroy() {
|
@@ -7903,7 +7947,7 @@
|
|
7903
7947
|
*/;
|
7904
7948
|
_proto.doTick = function doTick() {};
|
7905
7949
|
return TaskLoop;
|
7906
|
-
}();
|
7950
|
+
}(Logger);
|
7907
7951
|
|
7908
7952
|
var FragmentState = {
|
7909
7953
|
NOT_LOADED: "NOT_LOADED",
|
@@ -8922,8 +8966,8 @@
|
|
8922
8966
|
var _frag$decryptdata;
|
8923
8967
|
var byteRangeStart = start;
|
8924
8968
|
var byteRangeEnd = end;
|
8925
|
-
if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method)
|
8926
|
-
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
8969
|
+
if (frag.sn === 'initSegment' && isMethodFullSegmentAesCbc((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method)) {
|
8970
|
+
// MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
|
8927
8971
|
// has the unencrypted size specified in the range.
|
8928
8972
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
8929
8973
|
var fragmentLen = end - start;
|
@@ -8956,6 +9000,9 @@
|
|
8956
9000
|
(part ? part : frag).stats.aborted = true;
|
8957
9001
|
return new LoadError(errorData);
|
8958
9002
|
}
|
9003
|
+
function isMethodFullSegmentAesCbc(method) {
|
9004
|
+
return method === 'AES-128' || method === 'AES-256';
|
9005
|
+
}
|
8959
9006
|
var LoadError = /*#__PURE__*/function (_Error) {
|
8960
9007
|
_inheritsLoose(LoadError, _Error);
|
8961
9008
|
function LoadError(data) {
|
@@ -8969,37 +9016,65 @@
|
|
8969
9016
|
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
8970
9017
|
|
8971
9018
|
var AESCrypto = /*#__PURE__*/function () {
|
8972
|
-
function AESCrypto(subtle, iv) {
|
9019
|
+
function AESCrypto(subtle, iv, aesMode) {
|
8973
9020
|
this.subtle = void 0;
|
8974
9021
|
this.aesIV = void 0;
|
9022
|
+
this.aesMode = void 0;
|
8975
9023
|
this.subtle = subtle;
|
8976
9024
|
this.aesIV = iv;
|
9025
|
+
this.aesMode = aesMode;
|
8977
9026
|
}
|
8978
9027
|
var _proto = AESCrypto.prototype;
|
8979
9028
|
_proto.decrypt = function decrypt(data, key) {
|
8980
|
-
|
8981
|
-
|
8982
|
-
|
8983
|
-
|
9029
|
+
switch (this.aesMode) {
|
9030
|
+
case DecrypterAesMode.cbc:
|
9031
|
+
return this.subtle.decrypt({
|
9032
|
+
name: 'AES-CBC',
|
9033
|
+
iv: this.aesIV
|
9034
|
+
}, key, data);
|
9035
|
+
case DecrypterAesMode.ctr:
|
9036
|
+
return this.subtle.decrypt({
|
9037
|
+
name: 'AES-CTR',
|
9038
|
+
counter: this.aesIV,
|
9039
|
+
length: 64
|
9040
|
+
},
|
9041
|
+
//64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
|
9042
|
+
key, data);
|
9043
|
+
default:
|
9044
|
+
throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
|
9045
|
+
}
|
8984
9046
|
};
|
8985
9047
|
return AESCrypto;
|
8986
9048
|
}();
|
8987
9049
|
|
8988
9050
|
var FastAESKey = /*#__PURE__*/function () {
|
8989
|
-
function FastAESKey(subtle, key) {
|
9051
|
+
function FastAESKey(subtle, key, aesMode) {
|
8990
9052
|
this.subtle = void 0;
|
8991
9053
|
this.key = void 0;
|
9054
|
+
this.aesMode = void 0;
|
8992
9055
|
this.subtle = subtle;
|
8993
9056
|
this.key = key;
|
9057
|
+
this.aesMode = aesMode;
|
8994
9058
|
}
|
8995
9059
|
var _proto = FastAESKey.prototype;
|
8996
9060
|
_proto.expandKey = function expandKey() {
|
9061
|
+
var subtleAlgoName = getSubtleAlgoName(this.aesMode);
|
8997
9062
|
return this.subtle.importKey('raw', this.key, {
|
8998
|
-
name:
|
9063
|
+
name: subtleAlgoName
|
8999
9064
|
}, false, ['encrypt', 'decrypt']);
|
9000
9065
|
};
|
9001
9066
|
return FastAESKey;
|
9002
9067
|
}();
|
9068
|
+
function getSubtleAlgoName(aesMode) {
|
9069
|
+
switch (aesMode) {
|
9070
|
+
case DecrypterAesMode.cbc:
|
9071
|
+
return 'AES-CBC';
|
9072
|
+
case DecrypterAesMode.ctr:
|
9073
|
+
return 'AES-CTR';
|
9074
|
+
default:
|
9075
|
+
throw new Error("[FastAESKey] invalid aes mode " + aesMode);
|
9076
|
+
}
|
9077
|
+
}
|
9003
9078
|
|
9004
9079
|
// PKCS7
|
9005
9080
|
function removePadding(array) {
|
@@ -9252,7 +9327,8 @@
|
|
9252
9327
|
this.currentIV = null;
|
9253
9328
|
this.currentResult = null;
|
9254
9329
|
this.useSoftware = void 0;
|
9255
|
-
this.
|
9330
|
+
this.enableSoftwareAES = void 0;
|
9331
|
+
this.enableSoftwareAES = config.enableSoftwareAES;
|
9256
9332
|
this.removePKCS7Padding = removePKCS7Padding;
|
9257
9333
|
// built in decryptor expects PKCS7 padding
|
9258
9334
|
if (removePKCS7Padding) {
|
@@ -9265,9 +9341,7 @@
|
|
9265
9341
|
/* no-op */
|
9266
9342
|
}
|
9267
9343
|
}
|
9268
|
-
|
9269
|
-
this.useSoftware = true;
|
9270
|
-
}
|
9344
|
+
this.useSoftware = this.subtle === null;
|
9271
9345
|
}
|
9272
9346
|
var _proto = Decrypter.prototype;
|
9273
9347
|
_proto.destroy = function destroy() {
|
@@ -9304,11 +9378,11 @@
|
|
9304
9378
|
this.softwareDecrypter = null;
|
9305
9379
|
}
|
9306
9380
|
};
|
9307
|
-
_proto.decrypt = function decrypt(data, key, iv) {
|
9381
|
+
_proto.decrypt = function decrypt(data, key, iv, aesMode) {
|
9308
9382
|
var _this = this;
|
9309
9383
|
if (this.useSoftware) {
|
9310
9384
|
return new Promise(function (resolve, reject) {
|
9311
|
-
_this.softwareDecrypt(new Uint8Array(data), key, iv);
|
9385
|
+
_this.softwareDecrypt(new Uint8Array(data), key, iv, aesMode);
|
9312
9386
|
var decryptResult = _this.flush();
|
9313
9387
|
if (decryptResult) {
|
9314
9388
|
resolve(decryptResult.buffer);
|
@@ -9317,16 +9391,20 @@
|
|
9317
9391
|
}
|
9318
9392
|
});
|
9319
9393
|
}
|
9320
|
-
return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
|
9394
|
+
return this.webCryptoDecrypt(new Uint8Array(data), key, iv, aesMode);
|
9321
9395
|
}
|
9322
9396
|
|
9323
9397
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
9324
9398
|
// data is handled in the flush() call
|
9325
9399
|
;
|
9326
|
-
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
|
9400
|
+
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv, aesMode) {
|
9327
9401
|
var currentIV = this.currentIV,
|
9328
9402
|
currentResult = this.currentResult,
|
9329
9403
|
remainderData = this.remainderData;
|
9404
|
+
if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
|
9405
|
+
logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
|
9406
|
+
return null;
|
9407
|
+
}
|
9330
9408
|
this.logOnce('JS AES decrypt');
|
9331
9409
|
// The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
|
9332
9410
|
// This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
|
@@ -9359,12 +9437,12 @@
|
|
9359
9437
|
}
|
9360
9438
|
return result;
|
9361
9439
|
};
|
9362
|
-
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
|
9440
|
+
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv, aesMode) {
|
9363
9441
|
var _this2 = this;
|
9364
9442
|
var subtle = this.subtle;
|
9365
9443
|
if (this.key !== key || !this.fastAesKey) {
|
9366
9444
|
this.key = key;
|
9367
|
-
this.fastAesKey = new FastAESKey(subtle, key);
|
9445
|
+
this.fastAesKey = new FastAESKey(subtle, key, aesMode);
|
9368
9446
|
}
|
9369
9447
|
return this.fastAesKey.expandKey().then(function (aesKey) {
|
9370
9448
|
// decrypt using web crypto
|
@@ -9372,22 +9450,25 @@
|
|
9372
9450
|
return Promise.reject(new Error('web crypto not initialized'));
|
9373
9451
|
}
|
9374
9452
|
_this2.logOnce('WebCrypto AES decrypt');
|
9375
|
-
var crypto = new AESCrypto(subtle, new Uint8Array(iv));
|
9453
|
+
var crypto = new AESCrypto(subtle, new Uint8Array(iv), aesMode);
|
9376
9454
|
return crypto.decrypt(data.buffer, aesKey);
|
9377
9455
|
}).catch(function (err) {
|
9378
9456
|
logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
|
9379
|
-
return _this2.onWebCryptoError(data, key, iv);
|
9457
|
+
return _this2.onWebCryptoError(data, key, iv, aesMode);
|
9380
9458
|
});
|
9381
9459
|
};
|
9382
|
-
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
|
9383
|
-
|
9384
|
-
|
9385
|
-
|
9386
|
-
|
9387
|
-
|
9388
|
-
|
9460
|
+
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv, aesMode) {
|
9461
|
+
var enableSoftwareAES = this.enableSoftwareAES;
|
9462
|
+
if (enableSoftwareAES) {
|
9463
|
+
this.useSoftware = true;
|
9464
|
+
this.logEnabled = true;
|
9465
|
+
this.softwareDecrypt(data, key, iv, aesMode);
|
9466
|
+
var decryptResult = this.flush();
|
9467
|
+
if (decryptResult) {
|
9468
|
+
return decryptResult.buffer;
|
9469
|
+
}
|
9389
9470
|
}
|
9390
|
-
throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
|
9471
|
+
throw new Error('WebCrypto' + (enableSoftwareAES ? ' and softwareDecrypt' : '') + ': failed to decrypt data');
|
9391
9472
|
};
|
9392
9473
|
_proto.getValidChunk = function getValidChunk(data) {
|
9393
9474
|
var currentChunk = data;
|
@@ -9441,7 +9522,7 @@
|
|
9441
9522
|
_inheritsLoose(BaseStreamController, _TaskLoop);
|
9442
9523
|
function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
|
9443
9524
|
var _this;
|
9444
|
-
_this = _TaskLoop.call(this) || this;
|
9525
|
+
_this = _TaskLoop.call(this, logPrefix, hls.logger) || this;
|
9445
9526
|
_this.hls = void 0;
|
9446
9527
|
_this.fragPrevious = null;
|
9447
9528
|
_this.fragCurrent = null;
|
@@ -9466,25 +9547,87 @@
|
|
9466
9547
|
_this.startFragRequested = false;
|
9467
9548
|
_this.decrypter = void 0;
|
9468
9549
|
_this.initPTS = [];
|
9469
|
-
_this.
|
9470
|
-
_this.
|
9471
|
-
|
9472
|
-
|
9473
|
-
|
9550
|
+
_this.buffering = true;
|
9551
|
+
_this.onMediaSeeking = function () {
|
9552
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
9553
|
+
config = _assertThisInitialize.config,
|
9554
|
+
fragCurrent = _assertThisInitialize.fragCurrent,
|
9555
|
+
media = _assertThisInitialize.media,
|
9556
|
+
mediaBuffer = _assertThisInitialize.mediaBuffer,
|
9557
|
+
state = _assertThisInitialize.state;
|
9558
|
+
var currentTime = media ? media.currentTime : 0;
|
9559
|
+
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9560
|
+
_this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9561
|
+
if (_this.state === State.ENDED) {
|
9562
|
+
_this.resetLoadingState();
|
9563
|
+
} else if (fragCurrent) {
|
9564
|
+
// Seeking while frag load is in progress
|
9565
|
+
var tolerance = config.maxFragLookUpTolerance;
|
9566
|
+
var fragStartOffset = fragCurrent.start - tolerance;
|
9567
|
+
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9568
|
+
// if seeking out of buffered range or into new one
|
9569
|
+
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9570
|
+
var pastFragment = currentTime > fragEndOffset;
|
9571
|
+
// if the seek position is outside the current fragment range
|
9572
|
+
if (currentTime < fragStartOffset || pastFragment) {
|
9573
|
+
if (pastFragment && fragCurrent.loader) {
|
9574
|
+
_this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9575
|
+
fragCurrent.abortRequests();
|
9576
|
+
_this.resetLoadingState();
|
9577
|
+
}
|
9578
|
+
_this.fragPrevious = null;
|
9579
|
+
}
|
9580
|
+
}
|
9581
|
+
}
|
9582
|
+
if (media) {
|
9583
|
+
// Remove gap fragments
|
9584
|
+
_this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
|
9585
|
+
_this.lastCurrentTime = currentTime;
|
9586
|
+
}
|
9587
|
+
|
9588
|
+
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9589
|
+
if (!_this.loadedmetadata && !bufferInfo.len) {
|
9590
|
+
_this.nextLoadPosition = _this.startPosition = currentTime;
|
9591
|
+
}
|
9592
|
+
|
9593
|
+
// Async tick to speed up processing
|
9594
|
+
_this.tickImmediate();
|
9595
|
+
};
|
9596
|
+
_this.onMediaEnded = function () {
|
9597
|
+
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9598
|
+
_this.startPosition = _this.lastCurrentTime = 0;
|
9599
|
+
if (_this.playlistType === PlaylistLevelType.MAIN) {
|
9600
|
+
_this.hls.trigger(Events.MEDIA_ENDED, {
|
9601
|
+
stalled: false
|
9602
|
+
});
|
9603
|
+
}
|
9604
|
+
};
|
9474
9605
|
_this.playlistType = playlistType;
|
9475
|
-
_this.logPrefix = logPrefix;
|
9476
|
-
_this.log = logger.log.bind(logger, logPrefix + ":");
|
9477
|
-
_this.warn = logger.warn.bind(logger, logPrefix + ":");
|
9478
9606
|
_this.hls = hls;
|
9479
9607
|
_this.fragmentLoader = new FragmentLoader(hls.config);
|
9480
9608
|
_this.keyLoader = keyLoader;
|
9481
9609
|
_this.fragmentTracker = fragmentTracker;
|
9482
9610
|
_this.config = hls.config;
|
9483
9611
|
_this.decrypter = new Decrypter(hls.config);
|
9484
|
-
hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
|
9485
9612
|
return _this;
|
9486
9613
|
}
|
9487
9614
|
var _proto = BaseStreamController.prototype;
|
9615
|
+
_proto.registerListeners = function registerListeners() {
|
9616
|
+
var hls = this.hls;
|
9617
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9618
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9619
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9620
|
+
hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9621
|
+
hls.on(Events.ERROR, this.onError, this);
|
9622
|
+
};
|
9623
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
9624
|
+
var hls = this.hls;
|
9625
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9626
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9627
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9628
|
+
hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9629
|
+
hls.off(Events.ERROR, this.onError, this);
|
9630
|
+
};
|
9488
9631
|
_proto.doTick = function doTick() {
|
9489
9632
|
this.onTickEnd();
|
9490
9633
|
};
|
@@ -9508,6 +9651,12 @@
|
|
9508
9651
|
this.clearNextTick();
|
9509
9652
|
this.state = State.STOPPED;
|
9510
9653
|
};
|
9654
|
+
_proto.pauseBuffering = function pauseBuffering() {
|
9655
|
+
this.buffering = false;
|
9656
|
+
};
|
9657
|
+
_proto.resumeBuffering = function resumeBuffering() {
|
9658
|
+
this.buffering = true;
|
9659
|
+
};
|
9511
9660
|
_proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
|
9512
9661
|
// If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
|
9513
9662
|
// of nothing loading/loaded return false
|
@@ -9538,10 +9687,8 @@
|
|
9538
9687
|
};
|
9539
9688
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
9540
9689
|
var media = this.media = this.mediaBuffer = data.media;
|
9541
|
-
|
9542
|
-
|
9543
|
-
media.addEventListener('seeking', this.onvseeking);
|
9544
|
-
media.addEventListener('ended', this.onvended);
|
9690
|
+
media.addEventListener('seeking', this.onMediaSeeking);
|
9691
|
+
media.addEventListener('ended', this.onMediaEnded);
|
9545
9692
|
var config = this.config;
|
9546
9693
|
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
|
9547
9694
|
this.startLoad(config.startPosition);
|
@@ -9555,10 +9702,9 @@
|
|
9555
9702
|
}
|
9556
9703
|
|
9557
9704
|
// remove video listeners
|
9558
|
-
if (media
|
9559
|
-
media.removeEventListener('seeking', this.
|
9560
|
-
media.removeEventListener('ended', this.
|
9561
|
-
this.onvseeking = this.onvended = null;
|
9705
|
+
if (media) {
|
9706
|
+
media.removeEventListener('seeking', this.onMediaSeeking);
|
9707
|
+
media.removeEventListener('ended', this.onMediaEnded);
|
9562
9708
|
}
|
9563
9709
|
if (this.keyLoader) {
|
9564
9710
|
this.keyLoader.detach();
|
@@ -9568,54 +9714,8 @@
|
|
9568
9714
|
this.fragmentTracker.removeAllFragments();
|
9569
9715
|
this.stopLoad();
|
9570
9716
|
};
|
9571
|
-
_proto.
|
9572
|
-
|
9573
|
-
fragCurrent = this.fragCurrent,
|
9574
|
-
media = this.media,
|
9575
|
-
mediaBuffer = this.mediaBuffer,
|
9576
|
-
state = this.state;
|
9577
|
-
var currentTime = media ? media.currentTime : 0;
|
9578
|
-
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9579
|
-
this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9580
|
-
if (this.state === State.ENDED) {
|
9581
|
-
this.resetLoadingState();
|
9582
|
-
} else if (fragCurrent) {
|
9583
|
-
// Seeking while frag load is in progress
|
9584
|
-
var tolerance = config.maxFragLookUpTolerance;
|
9585
|
-
var fragStartOffset = fragCurrent.start - tolerance;
|
9586
|
-
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9587
|
-
// if seeking out of buffered range or into new one
|
9588
|
-
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9589
|
-
var pastFragment = currentTime > fragEndOffset;
|
9590
|
-
// if the seek position is outside the current fragment range
|
9591
|
-
if (currentTime < fragStartOffset || pastFragment) {
|
9592
|
-
if (pastFragment && fragCurrent.loader) {
|
9593
|
-
this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9594
|
-
fragCurrent.abortRequests();
|
9595
|
-
this.resetLoadingState();
|
9596
|
-
}
|
9597
|
-
this.fragPrevious = null;
|
9598
|
-
}
|
9599
|
-
}
|
9600
|
-
}
|
9601
|
-
if (media) {
|
9602
|
-
// Remove gap fragments
|
9603
|
-
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
9604
|
-
this.lastCurrentTime = currentTime;
|
9605
|
-
}
|
9606
|
-
|
9607
|
-
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9608
|
-
if (!this.loadedmetadata && !bufferInfo.len) {
|
9609
|
-
this.nextLoadPosition = this.startPosition = currentTime;
|
9610
|
-
}
|
9611
|
-
|
9612
|
-
// Async tick to speed up processing
|
9613
|
-
this.tickImmediate();
|
9614
|
-
};
|
9615
|
-
_proto.onMediaEnded = function onMediaEnded() {
|
9616
|
-
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9617
|
-
this.startPosition = this.lastCurrentTime = 0;
|
9618
|
-
};
|
9717
|
+
_proto.onManifestLoading = function onManifestLoading() {};
|
9718
|
+
_proto.onError = function onError(event, data) {};
|
9619
9719
|
_proto.onManifestLoaded = function onManifestLoaded(event, data) {
|
9620
9720
|
this.startTimeOffset = data.startTimeOffset;
|
9621
9721
|
this.initPTS = [];
|
@@ -9625,7 +9725,7 @@
|
|
9625
9725
|
this.stopLoad();
|
9626
9726
|
_TaskLoop.prototype.onHandlerDestroying.call(this);
|
9627
9727
|
// @ts-ignore
|
9628
|
-
this.hls = null;
|
9728
|
+
this.hls = this.onMediaSeeking = this.onMediaEnded = null;
|
9629
9729
|
};
|
9630
9730
|
_proto.onHandlerDestroyed = function onHandlerDestroyed() {
|
9631
9731
|
this.state = State.STOPPED;
|
@@ -9755,10 +9855,10 @@
|
|
9755
9855
|
var decryptData = frag.decryptdata;
|
9756
9856
|
|
9757
9857
|
// check to see if the payload needs to be decrypted
|
9758
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method
|
9858
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
|
9759
9859
|
var startTime = self.performance.now();
|
9760
9860
|
// decrypt init segment data
|
9761
|
-
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
9861
|
+
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
|
9762
9862
|
hls.trigger(Events.ERROR, {
|
9763
9863
|
type: ErrorTypes.MEDIA_ERROR,
|
9764
9864
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -9871,7 +9971,7 @@
|
|
9871
9971
|
}
|
9872
9972
|
var keyLoadingPromise = null;
|
9873
9973
|
if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
|
9874
|
-
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.
|
9974
|
+
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + " " + frag.level);
|
9875
9975
|
this.state = State.KEY_LOADING;
|
9876
9976
|
this.fragCurrent = frag;
|
9877
9977
|
keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
|
@@ -9902,7 +10002,7 @@
|
|
9902
10002
|
var partIndex = this.getNextPart(partList, frag, targetBufferTime);
|
9903
10003
|
if (partIndex > -1) {
|
9904
10004
|
var part = partList[partIndex];
|
9905
|
-
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.
|
10005
|
+
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.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
|
9906
10006
|
this.nextLoadPosition = part.start + part.duration;
|
9907
10007
|
this.state = State.FRAG_LOADING;
|
9908
10008
|
var _result;
|
@@ -9935,7 +10035,7 @@
|
|
9935
10035
|
}
|
9936
10036
|
}
|
9937
10037
|
}
|
9938
|
-
this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.
|
10038
|
+
this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
|
9939
10039
|
// Don't update nextLoadPosition for fragments which are not buffered
|
9940
10040
|
if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
|
9941
10041
|
this.nextLoadPosition = frag.start + frag.duration;
|
@@ -10496,7 +10596,7 @@
|
|
10496
10596
|
errorAction.resolved = true;
|
10497
10597
|
}
|
10498
10598
|
} else {
|
10499
|
-
|
10599
|
+
this.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
|
10500
10600
|
return;
|
10501
10601
|
}
|
10502
10602
|
} else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
|
@@ -10896,6 +10996,7 @@
|
|
10896
10996
|
*/
|
10897
10997
|
function getAudioConfig(observer, data, offset, audioCodec) {
|
10898
10998
|
var adtsObjectType;
|
10999
|
+
var originalAdtsObjectType;
|
10899
11000
|
var adtsExtensionSamplingIndex;
|
10900
11001
|
var adtsChannelConfig;
|
10901
11002
|
var config;
|
@@ -10903,7 +11004,7 @@
|
|
10903
11004
|
var manifestCodec = audioCodec;
|
10904
11005
|
var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
|
10905
11006
|
// byte 2
|
10906
|
-
adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
11007
|
+
adtsObjectType = originalAdtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
10907
11008
|
var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
|
10908
11009
|
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
|
10909
11010
|
var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
|
@@ -10920,8 +11021,8 @@
|
|
10920
11021
|
// byte 3
|
10921
11022
|
adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
|
10922
11023
|
logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
|
10923
|
-
//
|
10924
|
-
if (/firefox/i.test(userAgent)) {
|
11024
|
+
// Firefox and Pale Moon: freq less than 24kHz = AAC SBR (HE-AAC)
|
11025
|
+
if (/firefox|palemoon/i.test(userAgent)) {
|
10925
11026
|
if (adtsSamplingIndex >= 6) {
|
10926
11027
|
adtsObjectType = 5;
|
10927
11028
|
config = new Array(4);
|
@@ -11015,6 +11116,7 @@
|
|
11015
11116
|
samplerate: adtsSamplingRates[adtsSamplingIndex],
|
11016
11117
|
channelCount: adtsChannelConfig,
|
11017
11118
|
codec: 'mp4a.40.' + adtsObjectType,
|
11119
|
+
parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
|
11018
11120
|
manifestCodec: manifestCodec
|
11019
11121
|
};
|
11020
11122
|
}
|
@@ -11069,7 +11171,8 @@
|
|
11069
11171
|
track.channelCount = config.channelCount;
|
11070
11172
|
track.codec = config.codec;
|
11071
11173
|
track.manifestCodec = config.manifestCodec;
|
11072
|
-
|
11174
|
+
track.parsedCodec = config.parsedCodec;
|
11175
|
+
logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11073
11176
|
}
|
11074
11177
|
}
|
11075
11178
|
function getFrameDuration(samplerate) {
|
@@ -11667,69 +11770,173 @@
|
|
11667
11770
|
logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
|
11668
11771
|
}
|
11669
11772
|
};
|
11670
|
-
|
11671
|
-
|
11672
|
-
|
11673
|
-
|
11674
|
-
|
11675
|
-
|
11676
|
-
|
11677
|
-
|
11678
|
-
|
11679
|
-
|
11680
|
-
|
11681
|
-
|
11682
|
-
this.bitsAvailable = void 0;
|
11683
|
-
this.data = data;
|
11684
|
-
// the number of bytes left to examine in this.data
|
11685
|
-
this.bytesAvailable = data.byteLength;
|
11686
|
-
// the current word being examined
|
11687
|
-
this.word = 0; // :uint
|
11688
|
-
// the number of bits left to examine in the current word
|
11689
|
-
this.bitsAvailable = 0; // :uint
|
11690
|
-
}
|
11691
|
-
|
11692
|
-
// ():void
|
11693
|
-
var _proto = ExpGolomb.prototype;
|
11694
|
-
_proto.loadWord = function loadWord() {
|
11695
|
-
var data = this.data;
|
11696
|
-
var bytesAvailable = this.bytesAvailable;
|
11697
|
-
var position = data.byteLength - bytesAvailable;
|
11698
|
-
var workingBytes = new Uint8Array(4);
|
11699
|
-
var availableBytes = Math.min(4, bytesAvailable);
|
11700
|
-
if (availableBytes === 0) {
|
11701
|
-
throw new Error('no bytes available');
|
11702
|
-
}
|
11703
|
-
workingBytes.set(data.subarray(position, position + availableBytes));
|
11704
|
-
this.word = new DataView(workingBytes.buffer).getUint32(0);
|
11705
|
-
// track the amount of this.data that has been processed
|
11706
|
-
this.bitsAvailable = availableBytes * 8;
|
11707
|
-
this.bytesAvailable -= availableBytes;
|
11708
|
-
}
|
11773
|
+
_proto.parseNALu = function parseNALu(track, array) {
|
11774
|
+
var len = array.byteLength;
|
11775
|
+
var state = track.naluState || 0;
|
11776
|
+
var lastState = state;
|
11777
|
+
var units = [];
|
11778
|
+
var i = 0;
|
11779
|
+
var value;
|
11780
|
+
var overflow;
|
11781
|
+
var unitType;
|
11782
|
+
var lastUnitStart = -1;
|
11783
|
+
var lastUnitType = 0;
|
11784
|
+
// logger.log('PES:' + Hex.hexDump(array));
|
11709
11785
|
|
11710
|
-
|
11711
|
-
|
11712
|
-
|
11713
|
-
|
11714
|
-
|
11715
|
-
|
11716
|
-
|
11717
|
-
this.bitsAvailable -= count;
|
11718
|
-
} else {
|
11719
|
-
count -= this.bitsAvailable;
|
11720
|
-
skipBytes = count >> 3;
|
11721
|
-
count -= skipBytes << 3;
|
11722
|
-
this.bytesAvailable -= skipBytes;
|
11723
|
-
this.loadWord();
|
11724
|
-
this.word <<= count;
|
11725
|
-
this.bitsAvailable -= count;
|
11786
|
+
if (state === -1) {
|
11787
|
+
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
11788
|
+
lastUnitStart = 0;
|
11789
|
+
// NALu type is value read from offset 0
|
11790
|
+
lastUnitType = this.getNALuType(array, 0);
|
11791
|
+
state = 0;
|
11792
|
+
i = 1;
|
11726
11793
|
}
|
11727
|
-
|
11728
|
-
|
11729
|
-
|
11730
|
-
|
11731
|
-
|
11732
|
-
|
11794
|
+
while (i < len) {
|
11795
|
+
value = array[i++];
|
11796
|
+
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
11797
|
+
if (!state) {
|
11798
|
+
state = value ? 0 : 1;
|
11799
|
+
continue;
|
11800
|
+
}
|
11801
|
+
if (state === 1) {
|
11802
|
+
state = value ? 0 : 2;
|
11803
|
+
continue;
|
11804
|
+
}
|
11805
|
+
// here we have state either equal to 2 or 3
|
11806
|
+
if (!value) {
|
11807
|
+
state = 3;
|
11808
|
+
} else if (value === 1) {
|
11809
|
+
overflow = i - state - 1;
|
11810
|
+
if (lastUnitStart >= 0) {
|
11811
|
+
var unit = {
|
11812
|
+
data: array.subarray(lastUnitStart, overflow),
|
11813
|
+
type: lastUnitType
|
11814
|
+
};
|
11815
|
+
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
|
11816
|
+
units.push(unit);
|
11817
|
+
} else {
|
11818
|
+
// lastUnitStart is undefined => this is the first start code found in this PES packet
|
11819
|
+
// first check if start code delimiter is overlapping between 2 PES packets,
|
11820
|
+
// ie it started in last packet (lastState not zero)
|
11821
|
+
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
11822
|
+
var lastUnit = this.getLastNalUnit(track.samples);
|
11823
|
+
if (lastUnit) {
|
11824
|
+
if (lastState && i <= 4 - lastState) {
|
11825
|
+
// start delimiter overlapping between PES packets
|
11826
|
+
// strip start delimiter bytes from the end of last NAL unit
|
11827
|
+
// check if lastUnit had a state different from zero
|
11828
|
+
if (lastUnit.state) {
|
11829
|
+
// strip last bytes
|
11830
|
+
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
|
11831
|
+
}
|
11832
|
+
}
|
11833
|
+
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
|
11834
|
+
|
11835
|
+
if (overflow > 0) {
|
11836
|
+
// logger.log('first NALU found with overflow:' + overflow);
|
11837
|
+
lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
|
11838
|
+
lastUnit.state = 0;
|
11839
|
+
}
|
11840
|
+
}
|
11841
|
+
}
|
11842
|
+
// check if we can read unit type
|
11843
|
+
if (i < len) {
|
11844
|
+
unitType = this.getNALuType(array, i);
|
11845
|
+
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
11846
|
+
lastUnitStart = i;
|
11847
|
+
lastUnitType = unitType;
|
11848
|
+
state = 0;
|
11849
|
+
} else {
|
11850
|
+
// not enough byte to read unit type. let's read it on next PES parsing
|
11851
|
+
state = -1;
|
11852
|
+
}
|
11853
|
+
} else {
|
11854
|
+
state = 0;
|
11855
|
+
}
|
11856
|
+
}
|
11857
|
+
if (lastUnitStart >= 0 && state >= 0) {
|
11858
|
+
var _unit = {
|
11859
|
+
data: array.subarray(lastUnitStart, len),
|
11860
|
+
type: lastUnitType,
|
11861
|
+
state: state
|
11862
|
+
};
|
11863
|
+
units.push(_unit);
|
11864
|
+
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
11865
|
+
}
|
11866
|
+
// no NALu found
|
11867
|
+
if (units.length === 0) {
|
11868
|
+
// append pes.data to previous NAL unit
|
11869
|
+
var _lastUnit = this.getLastNalUnit(track.samples);
|
11870
|
+
if (_lastUnit) {
|
11871
|
+
_lastUnit.data = appendUint8Array(_lastUnit.data, array);
|
11872
|
+
}
|
11873
|
+
}
|
11874
|
+
track.naluState = state;
|
11875
|
+
return units;
|
11876
|
+
};
|
11877
|
+
return BaseVideoParser;
|
11878
|
+
}();
|
11879
|
+
|
11880
|
+
/**
|
11881
|
+
* Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
|
11882
|
+
*/
|
11883
|
+
|
11884
|
+
var ExpGolomb = /*#__PURE__*/function () {
|
11885
|
+
function ExpGolomb(data) {
|
11886
|
+
this.data = void 0;
|
11887
|
+
this.bytesAvailable = void 0;
|
11888
|
+
this.word = void 0;
|
11889
|
+
this.bitsAvailable = void 0;
|
11890
|
+
this.data = data;
|
11891
|
+
// the number of bytes left to examine in this.data
|
11892
|
+
this.bytesAvailable = data.byteLength;
|
11893
|
+
// the current word being examined
|
11894
|
+
this.word = 0; // :uint
|
11895
|
+
// the number of bits left to examine in the current word
|
11896
|
+
this.bitsAvailable = 0; // :uint
|
11897
|
+
}
|
11898
|
+
|
11899
|
+
// ():void
|
11900
|
+
var _proto = ExpGolomb.prototype;
|
11901
|
+
_proto.loadWord = function loadWord() {
|
11902
|
+
var data = this.data;
|
11903
|
+
var bytesAvailable = this.bytesAvailable;
|
11904
|
+
var position = data.byteLength - bytesAvailable;
|
11905
|
+
var workingBytes = new Uint8Array(4);
|
11906
|
+
var availableBytes = Math.min(4, bytesAvailable);
|
11907
|
+
if (availableBytes === 0) {
|
11908
|
+
throw new Error('no bytes available');
|
11909
|
+
}
|
11910
|
+
workingBytes.set(data.subarray(position, position + availableBytes));
|
11911
|
+
this.word = new DataView(workingBytes.buffer).getUint32(0);
|
11912
|
+
// track the amount of this.data that has been processed
|
11913
|
+
this.bitsAvailable = availableBytes * 8;
|
11914
|
+
this.bytesAvailable -= availableBytes;
|
11915
|
+
}
|
11916
|
+
|
11917
|
+
// (count:int):void
|
11918
|
+
;
|
11919
|
+
_proto.skipBits = function skipBits(count) {
|
11920
|
+
var skipBytes; // :int
|
11921
|
+
count = Math.min(count, this.bytesAvailable * 8 + this.bitsAvailable);
|
11922
|
+
if (this.bitsAvailable > count) {
|
11923
|
+
this.word <<= count;
|
11924
|
+
this.bitsAvailable -= count;
|
11925
|
+
} else {
|
11926
|
+
count -= this.bitsAvailable;
|
11927
|
+
skipBytes = count >> 3;
|
11928
|
+
count -= skipBytes << 3;
|
11929
|
+
this.bytesAvailable -= skipBytes;
|
11930
|
+
this.loadWord();
|
11931
|
+
this.word <<= count;
|
11932
|
+
this.bitsAvailable -= count;
|
11933
|
+
}
|
11934
|
+
}
|
11935
|
+
|
11936
|
+
// (size:int):uint
|
11937
|
+
;
|
11938
|
+
_proto.readBits = function readBits(size) {
|
11939
|
+
var bits = Math.min(this.bitsAvailable, size); // :uint
|
11733
11940
|
var valu = this.word >>> 32 - bits; // :uint
|
11734
11941
|
if (size > 32) {
|
11735
11942
|
logger.error('Cannot read more than 32 bits at a time');
|
@@ -11821,22 +12028,179 @@
|
|
11821
12028
|
;
|
11822
12029
|
_proto.readUInt = function readUInt() {
|
11823
12030
|
return this.readBits(32);
|
12031
|
+
};
|
12032
|
+
return ExpGolomb;
|
12033
|
+
}();
|
12034
|
+
|
12035
|
+
var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
|
12036
|
+
_inheritsLoose(AvcVideoParser, _BaseVideoParser);
|
12037
|
+
function AvcVideoParser() {
|
12038
|
+
return _BaseVideoParser.apply(this, arguments) || this;
|
12039
|
+
}
|
12040
|
+
var _proto = AvcVideoParser.prototype;
|
12041
|
+
_proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
|
12042
|
+
var _this = this;
|
12043
|
+
var units = this.parseNALu(track, pes.data);
|
12044
|
+
var VideoSample = this.VideoSample;
|
12045
|
+
var push;
|
12046
|
+
var spsfound = false;
|
12047
|
+
// free pes.data to save up some memory
|
12048
|
+
pes.data = null;
|
12049
|
+
|
12050
|
+
// if new NAL units found and last sample still there, let's push ...
|
12051
|
+
// this helps parsing streams with missing AUD (only do this if AUD never found)
|
12052
|
+
if (VideoSample && units.length && !track.audFound) {
|
12053
|
+
this.pushAccessUnit(VideoSample, track);
|
12054
|
+
VideoSample = this.VideoSample = this.createVideoSample(false, pes.pts, pes.dts, '');
|
12055
|
+
}
|
12056
|
+
units.forEach(function (unit) {
|
12057
|
+
var _VideoSample2;
|
12058
|
+
switch (unit.type) {
|
12059
|
+
// NDR
|
12060
|
+
case 1:
|
12061
|
+
{
|
12062
|
+
var iskey = false;
|
12063
|
+
push = true;
|
12064
|
+
var data = unit.data;
|
12065
|
+
// only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
|
12066
|
+
if (spsfound && data.length > 4) {
|
12067
|
+
// retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
|
12068
|
+
var sliceType = _this.readSliceType(data);
|
12069
|
+
// 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
|
12070
|
+
// SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
|
12071
|
+
// An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
|
12072
|
+
// I slice: A slice that is not an SI slice that is decoded using intra prediction only.
|
12073
|
+
// if (sliceType === 2 || sliceType === 7) {
|
12074
|
+
if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
|
12075
|
+
iskey = true;
|
12076
|
+
}
|
12077
|
+
}
|
12078
|
+
if (iskey) {
|
12079
|
+
var _VideoSample;
|
12080
|
+
// if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
|
12081
|
+
if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
|
12082
|
+
_this.pushAccessUnit(VideoSample, track);
|
12083
|
+
VideoSample = _this.VideoSample = null;
|
12084
|
+
}
|
12085
|
+
}
|
12086
|
+
if (!VideoSample) {
|
12087
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
|
12088
|
+
}
|
12089
|
+
VideoSample.frame = true;
|
12090
|
+
VideoSample.key = iskey;
|
12091
|
+
break;
|
12092
|
+
// IDR
|
12093
|
+
}
|
12094
|
+
case 5:
|
12095
|
+
push = true;
|
12096
|
+
// handle PES not starting with AUD
|
12097
|
+
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12098
|
+
if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
|
12099
|
+
_this.pushAccessUnit(VideoSample, track);
|
12100
|
+
VideoSample = _this.VideoSample = null;
|
12101
|
+
}
|
12102
|
+
if (!VideoSample) {
|
12103
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
|
12104
|
+
}
|
12105
|
+
VideoSample.key = true;
|
12106
|
+
VideoSample.frame = true;
|
12107
|
+
break;
|
12108
|
+
// SEI
|
12109
|
+
case 6:
|
12110
|
+
{
|
12111
|
+
push = true;
|
12112
|
+
parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
|
12113
|
+
break;
|
12114
|
+
// SPS
|
12115
|
+
}
|
12116
|
+
case 7:
|
12117
|
+
{
|
12118
|
+
var _track$pixelRatio, _track$pixelRatio2;
|
12119
|
+
push = true;
|
12120
|
+
spsfound = true;
|
12121
|
+
var sps = unit.data;
|
12122
|
+
var config = _this.readSPS(sps);
|
12123
|
+
if (!track.sps || track.width !== config.width || track.height !== config.height || ((_track$pixelRatio = track.pixelRatio) == null ? void 0 : _track$pixelRatio[0]) !== config.pixelRatio[0] || ((_track$pixelRatio2 = track.pixelRatio) == null ? void 0 : _track$pixelRatio2[1]) !== config.pixelRatio[1]) {
|
12124
|
+
track.width = config.width;
|
12125
|
+
track.height = config.height;
|
12126
|
+
track.pixelRatio = config.pixelRatio;
|
12127
|
+
track.sps = [sps];
|
12128
|
+
track.duration = duration;
|
12129
|
+
var codecarray = sps.subarray(1, 4);
|
12130
|
+
var codecstring = 'avc1.';
|
12131
|
+
for (var i = 0; i < 3; i++) {
|
12132
|
+
var h = codecarray[i].toString(16);
|
12133
|
+
if (h.length < 2) {
|
12134
|
+
h = '0' + h;
|
12135
|
+
}
|
12136
|
+
codecstring += h;
|
12137
|
+
}
|
12138
|
+
track.codec = codecstring;
|
12139
|
+
}
|
12140
|
+
break;
|
12141
|
+
}
|
12142
|
+
// PPS
|
12143
|
+
case 8:
|
12144
|
+
push = true;
|
12145
|
+
track.pps = [unit.data];
|
12146
|
+
break;
|
12147
|
+
// AUD
|
12148
|
+
case 9:
|
12149
|
+
push = true;
|
12150
|
+
track.audFound = true;
|
12151
|
+
if (VideoSample) {
|
12152
|
+
_this.pushAccessUnit(VideoSample, track);
|
12153
|
+
}
|
12154
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
|
12155
|
+
break;
|
12156
|
+
// Filler Data
|
12157
|
+
case 12:
|
12158
|
+
push = true;
|
12159
|
+
break;
|
12160
|
+
default:
|
12161
|
+
push = false;
|
12162
|
+
if (VideoSample) {
|
12163
|
+
VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
|
12164
|
+
}
|
12165
|
+
break;
|
12166
|
+
}
|
12167
|
+
if (VideoSample && push) {
|
12168
|
+
var _units = VideoSample.units;
|
12169
|
+
_units.push(unit);
|
12170
|
+
}
|
12171
|
+
});
|
12172
|
+
// if last PES packet, push samples
|
12173
|
+
if (last && VideoSample) {
|
12174
|
+
this.pushAccessUnit(VideoSample, track);
|
12175
|
+
this.VideoSample = null;
|
12176
|
+
}
|
12177
|
+
};
|
12178
|
+
_proto.getNALuType = function getNALuType(data, offset) {
|
12179
|
+
return data[offset] & 0x1f;
|
12180
|
+
};
|
12181
|
+
_proto.readSliceType = function readSliceType(data) {
|
12182
|
+
var eg = new ExpGolomb(data);
|
12183
|
+
// skip NALu type
|
12184
|
+
eg.readUByte();
|
12185
|
+
// discard first_mb_in_slice
|
12186
|
+
eg.readUEG();
|
12187
|
+
// return slice_type
|
12188
|
+
return eg.readUEG();
|
11824
12189
|
}
|
11825
12190
|
|
11826
12191
|
/**
|
11827
|
-
*
|
11828
|
-
* list is optionally transmitted as part of a sequence parameter
|
12192
|
+
* The scaling list is optionally transmitted as part of a sequence parameter
|
11829
12193
|
* set and is not relevant to transmuxing.
|
11830
12194
|
* @param count the number of entries in this scaling list
|
11831
12195
|
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
11832
12196
|
*/;
|
11833
|
-
_proto.skipScalingList = function skipScalingList(count) {
|
12197
|
+
_proto.skipScalingList = function skipScalingList(count, reader) {
|
11834
12198
|
var lastScale = 8;
|
11835
12199
|
var nextScale = 8;
|
11836
12200
|
var deltaScale;
|
11837
12201
|
for (var j = 0; j < count; j++) {
|
11838
12202
|
if (nextScale !== 0) {
|
11839
|
-
deltaScale =
|
12203
|
+
deltaScale = reader.readEG();
|
11840
12204
|
nextScale = (lastScale + deltaScale + 256) % 256;
|
11841
12205
|
}
|
11842
12206
|
lastScale = nextScale === 0 ? lastScale : nextScale;
|
@@ -11851,7 +12215,8 @@
|
|
11851
12215
|
* sequence parameter set, including the dimensions of the
|
11852
12216
|
* associated video frames.
|
11853
12217
|
*/;
|
11854
|
-
_proto.readSPS = function readSPS() {
|
12218
|
+
_proto.readSPS = function readSPS(sps) {
|
12219
|
+
var eg = new ExpGolomb(sps);
|
11855
12220
|
var frameCropLeftOffset = 0;
|
11856
12221
|
var frameCropRightOffset = 0;
|
11857
12222
|
var frameCropTopOffset = 0;
|
@@ -11859,13 +12224,13 @@
|
|
11859
12224
|
var numRefFramesInPicOrderCntCycle;
|
11860
12225
|
var scalingListCount;
|
11861
12226
|
var i;
|
11862
|
-
var readUByte =
|
11863
|
-
var readBits =
|
11864
|
-
var readUEG =
|
11865
|
-
var readBoolean =
|
11866
|
-
var skipBits =
|
11867
|
-
var skipEG =
|
11868
|
-
var skipUEG =
|
12227
|
+
var readUByte = eg.readUByte.bind(eg);
|
12228
|
+
var readBits = eg.readBits.bind(eg);
|
12229
|
+
var readUEG = eg.readUEG.bind(eg);
|
12230
|
+
var readBoolean = eg.readBoolean.bind(eg);
|
12231
|
+
var skipBits = eg.skipBits.bind(eg);
|
12232
|
+
var skipEG = eg.skipEG.bind(eg);
|
12233
|
+
var skipUEG = eg.skipUEG.bind(eg);
|
11869
12234
|
var skipScalingList = this.skipScalingList.bind(this);
|
11870
12235
|
readUByte();
|
11871
12236
|
var profileIdc = readUByte(); // profile_idc
|
@@ -11890,9 +12255,9 @@
|
|
11890
12255
|
if (readBoolean()) {
|
11891
12256
|
// seq_scaling_list_present_flag[ i ]
|
11892
12257
|
if (i < 6) {
|
11893
|
-
skipScalingList(16);
|
12258
|
+
skipScalingList(16, eg);
|
11894
12259
|
} else {
|
11895
|
-
skipScalingList(64);
|
12260
|
+
skipScalingList(64, eg);
|
11896
12261
|
}
|
11897
12262
|
}
|
11898
12263
|
}
|
@@ -11997,26 +12362,24 @@
|
|
11997
12362
|
pixelRatio: pixelRatio
|
11998
12363
|
};
|
11999
12364
|
};
|
12000
|
-
|
12001
|
-
|
12002
|
-
this.readUByte();
|
12003
|
-
// discard first_mb_in_slice
|
12004
|
-
this.readUEG();
|
12005
|
-
// return slice_type
|
12006
|
-
return this.readUEG();
|
12007
|
-
};
|
12008
|
-
return ExpGolomb;
|
12009
|
-
}();
|
12365
|
+
return AvcVideoParser;
|
12366
|
+
}(BaseVideoParser);
|
12010
12367
|
|
12011
|
-
var
|
12012
|
-
_inheritsLoose(
|
12013
|
-
function
|
12014
|
-
|
12015
|
-
|
12016
|
-
|
12017
|
-
|
12018
|
-
|
12019
|
-
|
12368
|
+
var HevcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
|
12369
|
+
_inheritsLoose(HevcVideoParser, _BaseVideoParser);
|
12370
|
+
function HevcVideoParser() {
|
12371
|
+
var _this;
|
12372
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
12373
|
+
args[_key] = arguments[_key];
|
12374
|
+
}
|
12375
|
+
_this = _BaseVideoParser.call.apply(_BaseVideoParser, [this].concat(args)) || this;
|
12376
|
+
_this.initVPS = null;
|
12377
|
+
return _this;
|
12378
|
+
}
|
12379
|
+
var _proto = HevcVideoParser.prototype;
|
12380
|
+
_proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
|
12381
|
+
var _this2 = this;
|
12382
|
+
var units = this.parseNALu(track, pes.data);
|
12020
12383
|
var VideoSample = this.VideoSample;
|
12021
12384
|
var push;
|
12022
12385
|
var spsfound = false;
|
@@ -12032,112 +12395,143 @@
|
|
12032
12395
|
units.forEach(function (unit) {
|
12033
12396
|
var _VideoSample2;
|
12034
12397
|
switch (unit.type) {
|
12035
|
-
//
|
12398
|
+
// NON-IDR, NON RANDOM ACCESS SLICE
|
12399
|
+
case 0:
|
12036
12400
|
case 1:
|
12037
|
-
|
12038
|
-
|
12039
|
-
|
12040
|
-
|
12041
|
-
|
12042
|
-
|
12043
|
-
|
12044
|
-
|
12045
|
-
|
12046
|
-
|
12047
|
-
|
12048
|
-
|
12049
|
-
|
12050
|
-
|
12051
|
-
|
12052
|
-
|
12053
|
-
|
12054
|
-
|
12055
|
-
|
12056
|
-
|
12057
|
-
|
12058
|
-
|
12059
|
-
|
12060
|
-
|
12061
|
-
|
12062
|
-
if (!VideoSample) {
|
12063
|
-
|
12401
|
+
case 2:
|
12402
|
+
case 3:
|
12403
|
+
case 4:
|
12404
|
+
case 5:
|
12405
|
+
case 6:
|
12406
|
+
case 7:
|
12407
|
+
case 8:
|
12408
|
+
case 9:
|
12409
|
+
if (!VideoSample) {
|
12410
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
|
12411
|
+
}
|
12412
|
+
VideoSample.frame = true;
|
12413
|
+
push = true;
|
12414
|
+
break;
|
12415
|
+
|
12416
|
+
// CRA, BLA (random access picture)
|
12417
|
+
case 16:
|
12418
|
+
case 17:
|
12419
|
+
case 18:
|
12420
|
+
case 21:
|
12421
|
+
push = true;
|
12422
|
+
if (spsfound) {
|
12423
|
+
var _VideoSample;
|
12424
|
+
// handle PES not starting with AUD
|
12425
|
+
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12426
|
+
if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
|
12427
|
+
_this2.pushAccessUnit(VideoSample, track);
|
12428
|
+
VideoSample = _this2.VideoSample = null;
|
12064
12429
|
}
|
12065
|
-
VideoSample.frame = true;
|
12066
|
-
VideoSample.key = iskey;
|
12067
|
-
break;
|
12068
|
-
// IDR
|
12069
12430
|
}
|
12070
|
-
|
12431
|
+
if (!VideoSample) {
|
12432
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12433
|
+
}
|
12434
|
+
VideoSample.key = true;
|
12435
|
+
VideoSample.frame = true;
|
12436
|
+
break;
|
12437
|
+
|
12438
|
+
// IDR
|
12439
|
+
case 19:
|
12440
|
+
case 20:
|
12071
12441
|
push = true;
|
12072
12442
|
// handle PES not starting with AUD
|
12073
12443
|
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12074
12444
|
if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
|
12075
|
-
|
12076
|
-
VideoSample =
|
12445
|
+
_this2.pushAccessUnit(VideoSample, track);
|
12446
|
+
VideoSample = _this2.VideoSample = null;
|
12077
12447
|
}
|
12078
12448
|
if (!VideoSample) {
|
12079
|
-
VideoSample =
|
12449
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12080
12450
|
}
|
12081
12451
|
VideoSample.key = true;
|
12082
12452
|
VideoSample.frame = true;
|
12083
12453
|
break;
|
12454
|
+
|
12084
12455
|
// SEI
|
12085
|
-
case
|
12086
|
-
|
12087
|
-
|
12088
|
-
|
12089
|
-
|
12090
|
-
|
12456
|
+
case 39:
|
12457
|
+
push = true;
|
12458
|
+
parseSEIMessageFromNALu(unit.data, 2,
|
12459
|
+
// NALu header size
|
12460
|
+
pes.pts, textTrack.samples);
|
12461
|
+
break;
|
12462
|
+
|
12463
|
+
// VPS
|
12464
|
+
case 32:
|
12465
|
+
push = true;
|
12466
|
+
if (!track.vps) {
|
12467
|
+
var config = _this2.readVPS(unit.data);
|
12468
|
+
track.params = _objectSpread2({}, config);
|
12469
|
+
_this2.initVPS = unit.data;
|
12091
12470
|
}
|
12092
|
-
|
12093
|
-
|
12094
|
-
|
12095
|
-
|
12096
|
-
|
12097
|
-
|
12098
|
-
|
12099
|
-
|
12100
|
-
if (
|
12101
|
-
|
12102
|
-
track.
|
12103
|
-
|
12104
|
-
|
12471
|
+
track.vps = [unit.data];
|
12472
|
+
break;
|
12473
|
+
|
12474
|
+
// SPS
|
12475
|
+
case 33:
|
12476
|
+
push = true;
|
12477
|
+
spsfound = true;
|
12478
|
+
if (typeof track.params === 'object') {
|
12479
|
+
if (track.vps !== undefined && track.vps[0] !== _this2.initVPS && track.sps !== undefined && !_this2.matchSPS(track.sps[0], unit.data)) {
|
12480
|
+
_this2.initVPS = track.vps[0];
|
12481
|
+
track.sps = track.pps = undefined;
|
12482
|
+
}
|
12483
|
+
if (!track.sps) {
|
12484
|
+
var _config = _this2.readSPS(unit.data);
|
12485
|
+
track.width = _config.width;
|
12486
|
+
track.height = _config.height;
|
12487
|
+
track.pixelRatio = _config.pixelRatio;
|
12105
12488
|
track.duration = duration;
|
12106
|
-
|
12107
|
-
|
12108
|
-
for (var
|
12109
|
-
|
12110
|
-
if (h.length < 2) {
|
12111
|
-
h = '0' + h;
|
12112
|
-
}
|
12113
|
-
codecstring += h;
|
12489
|
+
track.codec = _config.codecString;
|
12490
|
+
track.sps = [];
|
12491
|
+
for (var prop in _config.params) {
|
12492
|
+
track.params[prop] = _config.params[prop];
|
12114
12493
|
}
|
12115
|
-
track.codec = codecstring;
|
12116
12494
|
}
|
12117
|
-
|
12495
|
+
if (track.vps !== undefined && track.vps[0] === _this2.initVPS) {
|
12496
|
+
track.sps.push(unit.data);
|
12497
|
+
}
|
12118
12498
|
}
|
12499
|
+
if (!VideoSample) {
|
12500
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12501
|
+
}
|
12502
|
+
VideoSample.key = true;
|
12503
|
+
break;
|
12504
|
+
|
12119
12505
|
// PPS
|
12120
|
-
case
|
12506
|
+
case 34:
|
12121
12507
|
push = true;
|
12122
|
-
track.
|
12508
|
+
if (typeof track.params === 'object') {
|
12509
|
+
if (!track.pps) {
|
12510
|
+
track.pps = [];
|
12511
|
+
var _config2 = _this2.readPPS(unit.data);
|
12512
|
+
for (var _prop in _config2) {
|
12513
|
+
track.params[_prop] = _config2[_prop];
|
12514
|
+
}
|
12515
|
+
}
|
12516
|
+
if (_this2.initVPS !== null || track.pps.length === 0) {
|
12517
|
+
track.pps.push(unit.data);
|
12518
|
+
}
|
12519
|
+
}
|
12123
12520
|
break;
|
12124
|
-
|
12125
|
-
|
12521
|
+
|
12522
|
+
// ACCESS UNIT DELIMITER
|
12523
|
+
case 35:
|
12126
12524
|
push = true;
|
12127
12525
|
track.audFound = true;
|
12128
12526
|
if (VideoSample) {
|
12129
|
-
|
12527
|
+
_this2.pushAccessUnit(VideoSample, track);
|
12130
12528
|
}
|
12131
|
-
VideoSample =
|
12132
|
-
break;
|
12133
|
-
// Filler Data
|
12134
|
-
case 12:
|
12135
|
-
push = true;
|
12529
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
|
12136
12530
|
break;
|
12137
12531
|
default:
|
12138
12532
|
push = false;
|
12139
12533
|
if (VideoSample) {
|
12140
|
-
VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
|
12534
|
+
VideoSample.debug += 'unknown or irrelevant NAL ' + unit.type + ' ';
|
12141
12535
|
}
|
12142
12536
|
break;
|
12143
12537
|
}
|
@@ -12152,111 +12546,425 @@
|
|
12152
12546
|
this.VideoSample = null;
|
12153
12547
|
}
|
12154
12548
|
};
|
12155
|
-
_proto.
|
12156
|
-
|
12157
|
-
|
12158
|
-
|
12159
|
-
var
|
12160
|
-
var
|
12161
|
-
var
|
12162
|
-
|
12163
|
-
|
12164
|
-
|
12165
|
-
|
12166
|
-
|
12167
|
-
|
12168
|
-
if (state === -1) {
|
12169
|
-
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
12170
|
-
lastUnitStart = 0;
|
12171
|
-
// NALu type is value read from offset 0
|
12172
|
-
lastUnitType = array[0] & 0x1f;
|
12173
|
-
state = 0;
|
12174
|
-
i = 1;
|
12175
|
-
}
|
12176
|
-
while (i < len) {
|
12177
|
-
value = array[i++];
|
12178
|
-
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
12179
|
-
if (!state) {
|
12180
|
-
state = value ? 0 : 1;
|
12181
|
-
continue;
|
12182
|
-
}
|
12183
|
-
if (state === 1) {
|
12184
|
-
state = value ? 0 : 2;
|
12185
|
-
continue;
|
12549
|
+
_proto.getNALuType = function getNALuType(data, offset) {
|
12550
|
+
return (data[offset] & 0x7e) >>> 1;
|
12551
|
+
};
|
12552
|
+
_proto.ebsp2rbsp = function ebsp2rbsp(arr) {
|
12553
|
+
var dst = new Uint8Array(arr.byteLength);
|
12554
|
+
var dstIdx = 0;
|
12555
|
+
for (var i = 0; i < arr.byteLength; i++) {
|
12556
|
+
if (i >= 2) {
|
12557
|
+
// Unescape: Skip 0x03 after 00 00
|
12558
|
+
if (arr[i] === 0x03 && arr[i - 1] === 0x00 && arr[i - 2] === 0x00) {
|
12559
|
+
continue;
|
12560
|
+
}
|
12186
12561
|
}
|
12187
|
-
|
12188
|
-
|
12189
|
-
|
12190
|
-
|
12191
|
-
|
12192
|
-
|
12193
|
-
|
12194
|
-
|
12195
|
-
|
12196
|
-
|
12197
|
-
|
12198
|
-
|
12199
|
-
|
12200
|
-
|
12201
|
-
|
12202
|
-
|
12203
|
-
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
12204
|
-
var lastUnit = this.getLastNalUnit(track.samples);
|
12205
|
-
if (lastUnit) {
|
12206
|
-
if (lastState && i <= 4 - lastState) {
|
12207
|
-
// start delimiter overlapping between PES packets
|
12208
|
-
// strip start delimiter bytes from the end of last NAL unit
|
12209
|
-
// check if lastUnit had a state different from zero
|
12210
|
-
if (lastUnit.state) {
|
12211
|
-
// strip last bytes
|
12212
|
-
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
|
12213
|
-
}
|
12214
|
-
}
|
12215
|
-
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
|
12562
|
+
dst[dstIdx] = arr[i];
|
12563
|
+
dstIdx++;
|
12564
|
+
}
|
12565
|
+
return new Uint8Array(dst.buffer, 0, dstIdx);
|
12566
|
+
};
|
12567
|
+
_proto.readVPS = function readVPS(vps) {
|
12568
|
+
var eg = new ExpGolomb(vps);
|
12569
|
+
// remove header
|
12570
|
+
eg.readUByte();
|
12571
|
+
eg.readUByte();
|
12572
|
+
eg.readBits(4); // video_parameter_set_id
|
12573
|
+
eg.skipBits(2);
|
12574
|
+
eg.readBits(6); // max_layers_minus1
|
12575
|
+
var max_sub_layers_minus1 = eg.readBits(3);
|
12576
|
+
var temporal_id_nesting_flag = eg.readBoolean();
|
12577
|
+
// ...vui fps can be here, but empty fps value is not critical for metadata
|
12216
12578
|
|
12217
|
-
|
12218
|
-
|
12219
|
-
|
12220
|
-
|
12579
|
+
return {
|
12580
|
+
numTemporalLayers: max_sub_layers_minus1 + 1,
|
12581
|
+
temporalIdNested: temporal_id_nesting_flag
|
12582
|
+
};
|
12583
|
+
};
|
12584
|
+
_proto.readSPS = function readSPS(sps) {
|
12585
|
+
var eg = new ExpGolomb(this.ebsp2rbsp(sps));
|
12586
|
+
eg.readUByte();
|
12587
|
+
eg.readUByte();
|
12588
|
+
eg.readBits(4); //video_parameter_set_id
|
12589
|
+
var max_sub_layers_minus1 = eg.readBits(3);
|
12590
|
+
eg.readBoolean(); // temporal_id_nesting_flag
|
12591
|
+
|
12592
|
+
// profile_tier_level
|
12593
|
+
var general_profile_space = eg.readBits(2);
|
12594
|
+
var general_tier_flag = eg.readBoolean();
|
12595
|
+
var general_profile_idc = eg.readBits(5);
|
12596
|
+
var general_profile_compatibility_flags_1 = eg.readUByte();
|
12597
|
+
var general_profile_compatibility_flags_2 = eg.readUByte();
|
12598
|
+
var general_profile_compatibility_flags_3 = eg.readUByte();
|
12599
|
+
var general_profile_compatibility_flags_4 = eg.readUByte();
|
12600
|
+
var general_constraint_indicator_flags_1 = eg.readUByte();
|
12601
|
+
var general_constraint_indicator_flags_2 = eg.readUByte();
|
12602
|
+
var general_constraint_indicator_flags_3 = eg.readUByte();
|
12603
|
+
var general_constraint_indicator_flags_4 = eg.readUByte();
|
12604
|
+
var general_constraint_indicator_flags_5 = eg.readUByte();
|
12605
|
+
var general_constraint_indicator_flags_6 = eg.readUByte();
|
12606
|
+
var general_level_idc = eg.readUByte();
|
12607
|
+
var sub_layer_profile_present_flags = [];
|
12608
|
+
var sub_layer_level_present_flags = [];
|
12609
|
+
for (var i = 0; i < max_sub_layers_minus1; i++) {
|
12610
|
+
sub_layer_profile_present_flags.push(eg.readBoolean());
|
12611
|
+
sub_layer_level_present_flags.push(eg.readBoolean());
|
12612
|
+
}
|
12613
|
+
if (max_sub_layers_minus1 > 0) {
|
12614
|
+
for (var _i = max_sub_layers_minus1; _i < 8; _i++) {
|
12615
|
+
eg.readBits(2);
|
12616
|
+
}
|
12617
|
+
}
|
12618
|
+
for (var _i2 = 0; _i2 < max_sub_layers_minus1; _i2++) {
|
12619
|
+
if (sub_layer_profile_present_flags[_i2]) {
|
12620
|
+
eg.readUByte(); // sub_layer_profile_space, sub_layer_tier_flag, sub_layer_profile_idc
|
12621
|
+
eg.readUByte();
|
12622
|
+
eg.readUByte();
|
12623
|
+
eg.readUByte();
|
12624
|
+
eg.readUByte(); // sub_layer_profile_compatibility_flag
|
12625
|
+
eg.readUByte();
|
12626
|
+
eg.readUByte();
|
12627
|
+
eg.readUByte();
|
12628
|
+
eg.readUByte();
|
12629
|
+
eg.readUByte();
|
12630
|
+
eg.readUByte();
|
12631
|
+
}
|
12632
|
+
if (sub_layer_level_present_flags[_i2]) {
|
12633
|
+
eg.readUByte();
|
12634
|
+
}
|
12635
|
+
}
|
12636
|
+
eg.readUEG(); // seq_parameter_set_id
|
12637
|
+
var chroma_format_idc = eg.readUEG();
|
12638
|
+
if (chroma_format_idc == 3) {
|
12639
|
+
eg.skipBits(1); //separate_colour_plane_flag
|
12640
|
+
}
|
12641
|
+
var pic_width_in_luma_samples = eg.readUEG();
|
12642
|
+
var pic_height_in_luma_samples = eg.readUEG();
|
12643
|
+
var conformance_window_flag = eg.readBoolean();
|
12644
|
+
var pic_left_offset = 0,
|
12645
|
+
pic_right_offset = 0,
|
12646
|
+
pic_top_offset = 0,
|
12647
|
+
pic_bottom_offset = 0;
|
12648
|
+
if (conformance_window_flag) {
|
12649
|
+
pic_left_offset += eg.readUEG();
|
12650
|
+
pic_right_offset += eg.readUEG();
|
12651
|
+
pic_top_offset += eg.readUEG();
|
12652
|
+
pic_bottom_offset += eg.readUEG();
|
12653
|
+
}
|
12654
|
+
var bit_depth_luma_minus8 = eg.readUEG();
|
12655
|
+
var bit_depth_chroma_minus8 = eg.readUEG();
|
12656
|
+
var log2_max_pic_order_cnt_lsb_minus4 = eg.readUEG();
|
12657
|
+
var sub_layer_ordering_info_present_flag = eg.readBoolean();
|
12658
|
+
for (var _i3 = sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; _i3 <= max_sub_layers_minus1; _i3++) {
|
12659
|
+
eg.skipUEG(); // max_dec_pic_buffering_minus1[i]
|
12660
|
+
eg.skipUEG(); // max_num_reorder_pics[i]
|
12661
|
+
eg.skipUEG(); // max_latency_increase_plus1[i]
|
12662
|
+
}
|
12663
|
+
eg.skipUEG(); // log2_min_luma_coding_block_size_minus3
|
12664
|
+
eg.skipUEG(); // log2_diff_max_min_luma_coding_block_size
|
12665
|
+
eg.skipUEG(); // log2_min_transform_block_size_minus2
|
12666
|
+
eg.skipUEG(); // log2_diff_max_min_transform_block_size
|
12667
|
+
eg.skipUEG(); // max_transform_hierarchy_depth_inter
|
12668
|
+
eg.skipUEG(); // max_transform_hierarchy_depth_intra
|
12669
|
+
var scaling_list_enabled_flag = eg.readBoolean();
|
12670
|
+
if (scaling_list_enabled_flag) {
|
12671
|
+
var sps_scaling_list_data_present_flag = eg.readBoolean();
|
12672
|
+
if (sps_scaling_list_data_present_flag) {
|
12673
|
+
for (var sizeId = 0; sizeId < 4; sizeId++) {
|
12674
|
+
for (var matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
|
12675
|
+
var scaling_list_pred_mode_flag = eg.readBoolean();
|
12676
|
+
if (!scaling_list_pred_mode_flag) {
|
12677
|
+
eg.readUEG(); // scaling_list_pred_matrix_id_delta
|
12678
|
+
} else {
|
12679
|
+
var coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
|
12680
|
+
if (sizeId > 1) {
|
12681
|
+
eg.readEG();
|
12682
|
+
}
|
12683
|
+
for (var _i4 = 0; _i4 < coefNum; _i4++) {
|
12684
|
+
eg.readEG();
|
12685
|
+
}
|
12221
12686
|
}
|
12222
12687
|
}
|
12223
12688
|
}
|
12224
|
-
// check if we can read unit type
|
12225
|
-
if (i < len) {
|
12226
|
-
unitType = array[i] & 0x1f;
|
12227
|
-
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
12228
|
-
lastUnitStart = i;
|
12229
|
-
lastUnitType = unitType;
|
12230
|
-
state = 0;
|
12231
|
-
} else {
|
12232
|
-
// not enough byte to read unit type. let's read it on next PES parsing
|
12233
|
-
state = -1;
|
12234
|
-
}
|
12235
|
-
} else {
|
12236
|
-
state = 0;
|
12237
12689
|
}
|
12238
12690
|
}
|
12239
|
-
|
12240
|
-
|
12241
|
-
|
12242
|
-
|
12243
|
-
|
12244
|
-
|
12245
|
-
|
12246
|
-
|
12247
|
-
}
|
12248
|
-
|
12249
|
-
|
12250
|
-
|
12251
|
-
var
|
12252
|
-
if (
|
12253
|
-
|
12691
|
+
eg.readBoolean(); // amp_enabled_flag
|
12692
|
+
eg.readBoolean(); // sample_adaptive_offset_enabled_flag
|
12693
|
+
var pcm_enabled_flag = eg.readBoolean();
|
12694
|
+
if (pcm_enabled_flag) {
|
12695
|
+
eg.readUByte();
|
12696
|
+
eg.skipUEG();
|
12697
|
+
eg.skipUEG();
|
12698
|
+
eg.readBoolean();
|
12699
|
+
}
|
12700
|
+
var num_short_term_ref_pic_sets = eg.readUEG();
|
12701
|
+
var num_delta_pocs = 0;
|
12702
|
+
for (var _i5 = 0; _i5 < num_short_term_ref_pic_sets; _i5++) {
|
12703
|
+
var inter_ref_pic_set_prediction_flag = false;
|
12704
|
+
if (_i5 !== 0) {
|
12705
|
+
inter_ref_pic_set_prediction_flag = eg.readBoolean();
|
12706
|
+
}
|
12707
|
+
if (inter_ref_pic_set_prediction_flag) {
|
12708
|
+
if (_i5 === num_short_term_ref_pic_sets) {
|
12709
|
+
eg.readUEG();
|
12710
|
+
}
|
12711
|
+
eg.readBoolean();
|
12712
|
+
eg.readUEG();
|
12713
|
+
var next_num_delta_pocs = 0;
|
12714
|
+
for (var j = 0; j <= num_delta_pocs; j++) {
|
12715
|
+
var used_by_curr_pic_flag = eg.readBoolean();
|
12716
|
+
var use_delta_flag = false;
|
12717
|
+
if (!used_by_curr_pic_flag) {
|
12718
|
+
use_delta_flag = eg.readBoolean();
|
12719
|
+
}
|
12720
|
+
if (used_by_curr_pic_flag || use_delta_flag) {
|
12721
|
+
next_num_delta_pocs++;
|
12722
|
+
}
|
12723
|
+
}
|
12724
|
+
num_delta_pocs = next_num_delta_pocs;
|
12725
|
+
} else {
|
12726
|
+
var num_negative_pics = eg.readUEG();
|
12727
|
+
var num_positive_pics = eg.readUEG();
|
12728
|
+
num_delta_pocs = num_negative_pics + num_positive_pics;
|
12729
|
+
for (var _j = 0; _j < num_negative_pics; _j++) {
|
12730
|
+
eg.readUEG();
|
12731
|
+
eg.readBoolean();
|
12732
|
+
}
|
12733
|
+
for (var _j2 = 0; _j2 < num_positive_pics; _j2++) {
|
12734
|
+
eg.readUEG();
|
12735
|
+
eg.readBoolean();
|
12736
|
+
}
|
12737
|
+
}
|
12738
|
+
}
|
12739
|
+
var long_term_ref_pics_present_flag = eg.readBoolean();
|
12740
|
+
if (long_term_ref_pics_present_flag) {
|
12741
|
+
var num_long_term_ref_pics_sps = eg.readUEG();
|
12742
|
+
for (var _i6 = 0; _i6 < num_long_term_ref_pics_sps; _i6++) {
|
12743
|
+
for (var _j3 = 0; _j3 < log2_max_pic_order_cnt_lsb_minus4 + 4; _j3++) {
|
12744
|
+
eg.readBits(1);
|
12745
|
+
}
|
12746
|
+
eg.readBits(1);
|
12747
|
+
}
|
12748
|
+
}
|
12749
|
+
var min_spatial_segmentation_idc = 0;
|
12750
|
+
var sar_width = 1,
|
12751
|
+
sar_height = 1;
|
12752
|
+
var fps_fixed = true,
|
12753
|
+
fps_den = 1,
|
12754
|
+
fps_num = 0;
|
12755
|
+
eg.readBoolean(); // sps_temporal_mvp_enabled_flag
|
12756
|
+
eg.readBoolean(); // strong_intra_smoothing_enabled_flag
|
12757
|
+
var default_display_window_flag = false;
|
12758
|
+
var vui_parameters_present_flag = eg.readBoolean();
|
12759
|
+
if (vui_parameters_present_flag) {
|
12760
|
+
var aspect_ratio_info_present_flag = eg.readBoolean();
|
12761
|
+
if (aspect_ratio_info_present_flag) {
|
12762
|
+
var aspect_ratio_idc = eg.readUByte();
|
12763
|
+
var sar_width_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
|
12764
|
+
var sar_height_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
|
12765
|
+
if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
|
12766
|
+
sar_width = sar_width_table[aspect_ratio_idc - 1];
|
12767
|
+
sar_height = sar_height_table[aspect_ratio_idc - 1];
|
12768
|
+
} else if (aspect_ratio_idc === 255) {
|
12769
|
+
sar_width = eg.readBits(16);
|
12770
|
+
sar_height = eg.readBits(16);
|
12771
|
+
}
|
12772
|
+
}
|
12773
|
+
var overscan_info_present_flag = eg.readBoolean();
|
12774
|
+
if (overscan_info_present_flag) {
|
12775
|
+
eg.readBoolean();
|
12776
|
+
}
|
12777
|
+
var video_signal_type_present_flag = eg.readBoolean();
|
12778
|
+
if (video_signal_type_present_flag) {
|
12779
|
+
eg.readBits(3);
|
12780
|
+
eg.readBoolean();
|
12781
|
+
var colour_description_present_flag = eg.readBoolean();
|
12782
|
+
if (colour_description_present_flag) {
|
12783
|
+
eg.readUByte();
|
12784
|
+
eg.readUByte();
|
12785
|
+
eg.readUByte();
|
12786
|
+
}
|
12787
|
+
}
|
12788
|
+
var chroma_loc_info_present_flag = eg.readBoolean();
|
12789
|
+
if (chroma_loc_info_present_flag) {
|
12790
|
+
eg.readUEG();
|
12791
|
+
eg.readUEG();
|
12792
|
+
}
|
12793
|
+
eg.readBoolean(); // neutral_chroma_indication_flag
|
12794
|
+
eg.readBoolean(); // field_seq_flag
|
12795
|
+
eg.readBoolean(); // frame_field_info_present_flag
|
12796
|
+
default_display_window_flag = eg.readBoolean();
|
12797
|
+
if (default_display_window_flag) {
|
12798
|
+
pic_left_offset += eg.readUEG();
|
12799
|
+
pic_right_offset += eg.readUEG();
|
12800
|
+
pic_top_offset += eg.readUEG();
|
12801
|
+
pic_bottom_offset += eg.readUEG();
|
12802
|
+
}
|
12803
|
+
var vui_timing_info_present_flag = eg.readBoolean();
|
12804
|
+
if (vui_timing_info_present_flag) {
|
12805
|
+
fps_den = eg.readBits(32);
|
12806
|
+
fps_num = eg.readBits(32);
|
12807
|
+
var vui_poc_proportional_to_timing_flag = eg.readBoolean();
|
12808
|
+
if (vui_poc_proportional_to_timing_flag) {
|
12809
|
+
eg.readUEG();
|
12810
|
+
}
|
12811
|
+
var vui_hrd_parameters_present_flag = eg.readBoolean();
|
12812
|
+
if (vui_hrd_parameters_present_flag) {
|
12813
|
+
//const commonInfPresentFlag = true;
|
12814
|
+
//if (commonInfPresentFlag) {
|
12815
|
+
var nal_hrd_parameters_present_flag = eg.readBoolean();
|
12816
|
+
var vcl_hrd_parameters_present_flag = eg.readBoolean();
|
12817
|
+
var sub_pic_hrd_params_present_flag = false;
|
12818
|
+
if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
|
12819
|
+
sub_pic_hrd_params_present_flag = eg.readBoolean();
|
12820
|
+
if (sub_pic_hrd_params_present_flag) {
|
12821
|
+
eg.readUByte();
|
12822
|
+
eg.readBits(5);
|
12823
|
+
eg.readBoolean();
|
12824
|
+
eg.readBits(5);
|
12825
|
+
}
|
12826
|
+
eg.readBits(4); // bit_rate_scale
|
12827
|
+
eg.readBits(4); // cpb_size_scale
|
12828
|
+
if (sub_pic_hrd_params_present_flag) {
|
12829
|
+
eg.readBits(4);
|
12830
|
+
}
|
12831
|
+
eg.readBits(5);
|
12832
|
+
eg.readBits(5);
|
12833
|
+
eg.readBits(5);
|
12834
|
+
}
|
12835
|
+
//}
|
12836
|
+
for (var _i7 = 0; _i7 <= max_sub_layers_minus1; _i7++) {
|
12837
|
+
fps_fixed = eg.readBoolean(); // fixed_pic_rate_general_flag
|
12838
|
+
var fixed_pic_rate_within_cvs_flag = fps_fixed || eg.readBoolean();
|
12839
|
+
var low_delay_hrd_flag = false;
|
12840
|
+
if (fixed_pic_rate_within_cvs_flag) {
|
12841
|
+
eg.readEG();
|
12842
|
+
} else {
|
12843
|
+
low_delay_hrd_flag = eg.readBoolean();
|
12844
|
+
}
|
12845
|
+
var cpb_cnt = low_delay_hrd_flag ? 1 : eg.readUEG() + 1;
|
12846
|
+
if (nal_hrd_parameters_present_flag) {
|
12847
|
+
for (var _j4 = 0; _j4 < cpb_cnt; _j4++) {
|
12848
|
+
eg.readUEG();
|
12849
|
+
eg.readUEG();
|
12850
|
+
if (sub_pic_hrd_params_present_flag) {
|
12851
|
+
eg.readUEG();
|
12852
|
+
eg.readUEG();
|
12853
|
+
}
|
12854
|
+
eg.skipBits(1);
|
12855
|
+
}
|
12856
|
+
}
|
12857
|
+
if (vcl_hrd_parameters_present_flag) {
|
12858
|
+
for (var _j5 = 0; _j5 < cpb_cnt; _j5++) {
|
12859
|
+
eg.readUEG();
|
12860
|
+
eg.readUEG();
|
12861
|
+
if (sub_pic_hrd_params_present_flag) {
|
12862
|
+
eg.readUEG();
|
12863
|
+
eg.readUEG();
|
12864
|
+
}
|
12865
|
+
eg.skipBits(1);
|
12866
|
+
}
|
12867
|
+
}
|
12868
|
+
}
|
12869
|
+
}
|
12254
12870
|
}
|
12871
|
+
var bitstream_restriction_flag = eg.readBoolean();
|
12872
|
+
if (bitstream_restriction_flag) {
|
12873
|
+
eg.readBoolean(); // tiles_fixed_structure_flag
|
12874
|
+
eg.readBoolean(); // motion_vectors_over_pic_boundaries_flag
|
12875
|
+
eg.readBoolean(); // restricted_ref_pic_lists_flag
|
12876
|
+
min_spatial_segmentation_idc = eg.readUEG();
|
12877
|
+
}
|
12878
|
+
}
|
12879
|
+
var width = pic_width_in_luma_samples,
|
12880
|
+
height = pic_height_in_luma_samples;
|
12881
|
+
if (conformance_window_flag || default_display_window_flag) {
|
12882
|
+
var chroma_scale_w = 1,
|
12883
|
+
chroma_scale_h = 1;
|
12884
|
+
if (chroma_format_idc === 1) {
|
12885
|
+
// YUV 420
|
12886
|
+
chroma_scale_w = chroma_scale_h = 2;
|
12887
|
+
} else if (chroma_format_idc == 2) {
|
12888
|
+
// YUV 422
|
12889
|
+
chroma_scale_w = 2;
|
12890
|
+
}
|
12891
|
+
width = pic_width_in_luma_samples - chroma_scale_w * pic_right_offset - chroma_scale_w * pic_left_offset;
|
12892
|
+
height = pic_height_in_luma_samples - chroma_scale_h * pic_bottom_offset - chroma_scale_h * pic_top_offset;
|
12893
|
+
}
|
12894
|
+
var profile_space_string = general_profile_space ? ['A', 'B', 'C'][general_profile_space] : '';
|
12895
|
+
var profile_compatibility_buf = general_profile_compatibility_flags_1 << 24 | general_profile_compatibility_flags_2 << 16 | general_profile_compatibility_flags_3 << 8 | general_profile_compatibility_flags_4;
|
12896
|
+
var profile_compatibility_rev = 0;
|
12897
|
+
for (var _i8 = 0; _i8 < 32; _i8++) {
|
12898
|
+
profile_compatibility_rev = (profile_compatibility_rev | (profile_compatibility_buf >> _i8 & 1) << 31 - _i8) >>> 0; // reverse bit position (and cast as UInt32)
|
12899
|
+
}
|
12900
|
+
var profile_compatibility_flags_string = profile_compatibility_rev.toString(16);
|
12901
|
+
if (general_profile_idc === 1 && profile_compatibility_flags_string === '2') {
|
12902
|
+
profile_compatibility_flags_string = '6';
|
12903
|
+
}
|
12904
|
+
var tier_flag_string = general_tier_flag ? 'H' : 'L';
|
12905
|
+
return {
|
12906
|
+
codecString: "hvc1." + profile_space_string + general_profile_idc + "." + profile_compatibility_flags_string + "." + tier_flag_string + general_level_idc + ".B0",
|
12907
|
+
params: {
|
12908
|
+
general_tier_flag: general_tier_flag,
|
12909
|
+
general_profile_idc: general_profile_idc,
|
12910
|
+
general_profile_space: general_profile_space,
|
12911
|
+
general_profile_compatibility_flags: [general_profile_compatibility_flags_1, general_profile_compatibility_flags_2, general_profile_compatibility_flags_3, general_profile_compatibility_flags_4],
|
12912
|
+
general_constraint_indicator_flags: [general_constraint_indicator_flags_1, general_constraint_indicator_flags_2, general_constraint_indicator_flags_3, general_constraint_indicator_flags_4, general_constraint_indicator_flags_5, general_constraint_indicator_flags_6],
|
12913
|
+
general_level_idc: general_level_idc,
|
12914
|
+
bit_depth: bit_depth_luma_minus8 + 8,
|
12915
|
+
bit_depth_luma_minus8: bit_depth_luma_minus8,
|
12916
|
+
bit_depth_chroma_minus8: bit_depth_chroma_minus8,
|
12917
|
+
min_spatial_segmentation_idc: min_spatial_segmentation_idc,
|
12918
|
+
chroma_format_idc: chroma_format_idc,
|
12919
|
+
frame_rate: {
|
12920
|
+
fixed: fps_fixed,
|
12921
|
+
fps: fps_num / fps_den
|
12922
|
+
}
|
12923
|
+
},
|
12924
|
+
width: width,
|
12925
|
+
height: height,
|
12926
|
+
pixelRatio: [sar_width, sar_height]
|
12927
|
+
};
|
12928
|
+
};
|
12929
|
+
_proto.readPPS = function readPPS(pps) {
|
12930
|
+
var eg = new ExpGolomb(this.ebsp2rbsp(pps));
|
12931
|
+
eg.readUByte();
|
12932
|
+
eg.readUByte();
|
12933
|
+
eg.skipUEG(); // pic_parameter_set_id
|
12934
|
+
eg.skipUEG(); // seq_parameter_set_id
|
12935
|
+
eg.skipBits(2); // dependent_slice_segments_enabled_flag, output_flag_present_flag
|
12936
|
+
eg.skipBits(3); // num_extra_slice_header_bits
|
12937
|
+
eg.skipBits(2); // sign_data_hiding_enabled_flag, cabac_init_present_flag
|
12938
|
+
eg.skipUEG();
|
12939
|
+
eg.skipUEG();
|
12940
|
+
eg.skipEG(); // init_qp_minus26
|
12941
|
+
eg.skipBits(2); // constrained_intra_pred_flag, transform_skip_enabled_flag
|
12942
|
+
var cu_qp_delta_enabled_flag = eg.readBoolean();
|
12943
|
+
if (cu_qp_delta_enabled_flag) {
|
12944
|
+
eg.skipUEG();
|
12945
|
+
}
|
12946
|
+
eg.skipEG(); // cb_qp_offset
|
12947
|
+
eg.skipEG(); // cr_qp_offset
|
12948
|
+
eg.skipBits(4); // pps_slice_chroma_qp_offsets_present_flag, weighted_pred_flag, weighted_bipred_flag, transquant_bypass_enabled_flag
|
12949
|
+
var tiles_enabled_flag = eg.readBoolean();
|
12950
|
+
var entropy_coding_sync_enabled_flag = eg.readBoolean();
|
12951
|
+
var parallelismType = 1; // slice-based parallel decoding
|
12952
|
+
if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) {
|
12953
|
+
parallelismType = 0; // mixed-type parallel decoding
|
12954
|
+
} else if (entropy_coding_sync_enabled_flag) {
|
12955
|
+
parallelismType = 3; // wavefront-based parallel decoding
|
12956
|
+
} else if (tiles_enabled_flag) {
|
12957
|
+
parallelismType = 2; // tile-based parallel decoding
|
12255
12958
|
}
|
12256
|
-
|
12257
|
-
|
12959
|
+
return {
|
12960
|
+
parallelismType: parallelismType
|
12961
|
+
};
|
12258
12962
|
};
|
12259
|
-
|
12963
|
+
_proto.matchSPS = function matchSPS(sps1, sps2) {
|
12964
|
+
// compare without headers and VPS related params
|
12965
|
+
return String.fromCharCode.apply(null, sps1).substr(3) === String.fromCharCode.apply(null, sps2).substr(3);
|
12966
|
+
};
|
12967
|
+
return HevcVideoParser;
|
12260
12968
|
}(BaseVideoParser);
|
12261
12969
|
|
12262
12970
|
/**
|
@@ -12274,7 +12982,7 @@
|
|
12274
12982
|
}
|
12275
12983
|
var _proto = SampleAesDecrypter.prototype;
|
12276
12984
|
_proto.decryptBuffer = function decryptBuffer(encryptedData) {
|
12277
|
-
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
|
12985
|
+
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer, DecrypterAesMode.cbc);
|
12278
12986
|
}
|
12279
12987
|
|
12280
12988
|
// AAC - encrypt all full 16 bytes blocks starting from offset 16
|
@@ -12393,7 +13101,7 @@
|
|
12393
13101
|
this.observer = observer;
|
12394
13102
|
this.config = config;
|
12395
13103
|
this.typeSupported = typeSupported;
|
12396
|
-
this.videoParser =
|
13104
|
+
this.videoParser = null;
|
12397
13105
|
}
|
12398
13106
|
TSDemuxer.probe = function probe(data) {
|
12399
13107
|
var syncOffset = TSDemuxer.syncOffset(data);
|
@@ -12563,7 +13271,19 @@
|
|
12563
13271
|
case videoPid:
|
12564
13272
|
if (stt) {
|
12565
13273
|
if (videoData && (pes = parsePES(videoData))) {
|
12566
|
-
this.videoParser
|
13274
|
+
if (this.videoParser === null) {
|
13275
|
+
switch (videoTrack.segmentCodec) {
|
13276
|
+
case 'avc':
|
13277
|
+
this.videoParser = new AvcVideoParser();
|
13278
|
+
break;
|
13279
|
+
case 'hevc':
|
13280
|
+
this.videoParser = new HevcVideoParser();
|
13281
|
+
break;
|
13282
|
+
}
|
13283
|
+
}
|
13284
|
+
if (this.videoParser !== null) {
|
13285
|
+
this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
|
13286
|
+
}
|
12567
13287
|
}
|
12568
13288
|
videoData = {
|
12569
13289
|
data: [],
|
@@ -12726,8 +13446,20 @@
|
|
12726
13446
|
// try to parse last PES packets
|
12727
13447
|
var pes;
|
12728
13448
|
if (videoData && (pes = parsePES(videoData))) {
|
12729
|
-
this.videoParser
|
12730
|
-
|
13449
|
+
if (this.videoParser === null) {
|
13450
|
+
switch (videoTrack.segmentCodec) {
|
13451
|
+
case 'avc':
|
13452
|
+
this.videoParser = new AvcVideoParser();
|
13453
|
+
break;
|
13454
|
+
case 'hevc':
|
13455
|
+
this.videoParser = new HevcVideoParser();
|
13456
|
+
break;
|
13457
|
+
}
|
13458
|
+
}
|
13459
|
+
if (this.videoParser !== null) {
|
13460
|
+
this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
|
13461
|
+
videoTrack.pesData = null;
|
13462
|
+
}
|
12731
13463
|
} else {
|
12732
13464
|
// either avcData null or PES truncated, keep it for next frag parsing
|
12733
13465
|
videoTrack.pesData = videoData;
|
@@ -13059,7 +13791,12 @@
|
|
13059
13791
|
logger.warn('Unsupported EC-3 in M2TS found');
|
13060
13792
|
break;
|
13061
13793
|
case 0x24:
|
13062
|
-
|
13794
|
+
// ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
|
13795
|
+
if (result.videoPid === -1) {
|
13796
|
+
result.videoPid = pid;
|
13797
|
+
result.segmentVideoCodec = 'hevc';
|
13798
|
+
logger.log('HEVC in M2TS found');
|
13799
|
+
}
|
13063
13800
|
break;
|
13064
13801
|
}
|
13065
13802
|
// move to the next table entry
|
@@ -13287,6 +14024,8 @@
|
|
13287
14024
|
avc1: [],
|
13288
14025
|
// codingname
|
13289
14026
|
avcC: [],
|
14027
|
+
hvc1: [],
|
14028
|
+
hvcC: [],
|
13290
14029
|
btrt: [],
|
13291
14030
|
dinf: [],
|
13292
14031
|
dref: [],
|
@@ -13714,8 +14453,10 @@
|
|
13714
14453
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
13715
14454
|
}
|
13716
14455
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
13717
|
-
} else {
|
14456
|
+
} else if (track.segmentCodec === 'avc') {
|
13718
14457
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
14458
|
+
} else {
|
14459
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.hvc1(track));
|
13719
14460
|
}
|
13720
14461
|
};
|
13721
14462
|
MP4.tkhd = function tkhd(track) {
|
@@ -13853,6 +14594,84 @@
|
|
13853
14594
|
var result = appendUint8Array(MP4.FTYP, movie);
|
13854
14595
|
return result;
|
13855
14596
|
};
|
14597
|
+
MP4.hvc1 = function hvc1(track) {
|
14598
|
+
var ps = track.params;
|
14599
|
+
var units = [track.vps, track.sps, track.pps];
|
14600
|
+
var NALuLengthSize = 4;
|
14601
|
+
var config = new Uint8Array([0x01, ps.general_profile_space << 6 | (ps.general_tier_flag ? 32 : 0) | ps.general_profile_idc, ps.general_profile_compatibility_flags[0], ps.general_profile_compatibility_flags[1], ps.general_profile_compatibility_flags[2], ps.general_profile_compatibility_flags[3], ps.general_constraint_indicator_flags[0], ps.general_constraint_indicator_flags[1], ps.general_constraint_indicator_flags[2], ps.general_constraint_indicator_flags[3], ps.general_constraint_indicator_flags[4], ps.general_constraint_indicator_flags[5], ps.general_level_idc, 240 | ps.min_spatial_segmentation_idc >> 8, 255 & ps.min_spatial_segmentation_idc, 252 | ps.parallelismType, 252 | ps.chroma_format_idc, 248 | ps.bit_depth_luma_minus8, 248 | ps.bit_depth_chroma_minus8, 0x00, parseInt(ps.frame_rate.fps), NALuLengthSize - 1 | ps.temporal_id_nested << 2 | ps.num_temporal_layers << 3 | (ps.frame_rate.fixed ? 64 : 0), units.length]);
|
14602
|
+
|
14603
|
+
// compute hvcC size in bytes
|
14604
|
+
var length = config.length;
|
14605
|
+
for (var i = 0; i < units.length; i += 1) {
|
14606
|
+
length += 3;
|
14607
|
+
for (var j = 0; j < units[i].length; j += 1) {
|
14608
|
+
length += 2 + units[i][j].length;
|
14609
|
+
}
|
14610
|
+
}
|
14611
|
+
var hvcC = new Uint8Array(length);
|
14612
|
+
hvcC.set(config, 0);
|
14613
|
+
length = config.length;
|
14614
|
+
// append parameter set units: one vps, one or more sps and pps
|
14615
|
+
var iMax = units.length - 1;
|
14616
|
+
for (var _i = 0; _i < units.length; _i += 1) {
|
14617
|
+
hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
|
14618
|
+
length += 3;
|
14619
|
+
for (var _j = 0; _j < units[_i].length; _j += 1) {
|
14620
|
+
hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
|
14621
|
+
length += 2;
|
14622
|
+
hvcC.set(units[_i][_j], length);
|
14623
|
+
length += units[_i][_j].length;
|
14624
|
+
}
|
14625
|
+
}
|
14626
|
+
var hvcc = MP4.box(MP4.types.hvcC, hvcC);
|
14627
|
+
var width = track.width;
|
14628
|
+
var height = track.height;
|
14629
|
+
var hSpacing = track.pixelRatio[0];
|
14630
|
+
var vSpacing = track.pixelRatio[1];
|
14631
|
+
return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
|
14632
|
+
// reserved
|
14633
|
+
0x00, 0x00, 0x00,
|
14634
|
+
// reserved
|
14635
|
+
0x00, 0x01,
|
14636
|
+
// data_reference_index
|
14637
|
+
0x00, 0x00,
|
14638
|
+
// pre_defined
|
14639
|
+
0x00, 0x00,
|
14640
|
+
// reserved
|
14641
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
14642
|
+
// pre_defined
|
14643
|
+
width >> 8 & 0xff, width & 0xff,
|
14644
|
+
// width
|
14645
|
+
height >> 8 & 0xff, height & 0xff,
|
14646
|
+
// height
|
14647
|
+
0x00, 0x48, 0x00, 0x00,
|
14648
|
+
// horizresolution
|
14649
|
+
0x00, 0x48, 0x00, 0x00,
|
14650
|
+
// vertresolution
|
14651
|
+
0x00, 0x00, 0x00, 0x00,
|
14652
|
+
// reserved
|
14653
|
+
0x00, 0x01,
|
14654
|
+
// frame_count
|
14655
|
+
0x12, 0x64, 0x61, 0x69, 0x6c,
|
14656
|
+
// dailymotion/hls.js
|
14657
|
+
0x79, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x6c, 0x73, 0x2e, 0x6a, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
14658
|
+
// compressorname
|
14659
|
+
0x00, 0x18,
|
14660
|
+
// depth = 24
|
14661
|
+
0x11, 0x11]),
|
14662
|
+
// pre_defined = -1
|
14663
|
+
hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
|
14664
|
+
// bufferSizeDB
|
14665
|
+
0x00, 0x2d, 0xc6, 0xc0,
|
14666
|
+
// maxBitrate
|
14667
|
+
0x00, 0x2d, 0xc6, 0xc0])),
|
14668
|
+
// avgBitrate
|
14669
|
+
MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
|
14670
|
+
// hSpacing
|
14671
|
+
hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
|
14672
|
+
// vSpacing
|
14673
|
+
vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
|
14674
|
+
};
|
13856
14675
|
return MP4;
|
13857
14676
|
}();
|
13858
14677
|
MP4.types = void 0;
|
@@ -14254,9 +15073,9 @@
|
|
14254
15073
|
var foundOverlap = delta < -1;
|
14255
15074
|
if (foundHole || foundOverlap) {
|
14256
15075
|
if (foundHole) {
|
14257
|
-
logger.warn("
|
15076
|
+
logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
|
14258
15077
|
} else {
|
14259
|
-
logger.warn("
|
15078
|
+
logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
|
14260
15079
|
}
|
14261
15080
|
if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
|
14262
15081
|
firstDTS = nextAvcDts;
|
@@ -14265,12 +15084,24 @@
|
|
14265
15084
|
inputSamples[0].dts = firstDTS;
|
14266
15085
|
inputSamples[0].pts = firstPTS;
|
14267
15086
|
} else {
|
15087
|
+
var isPTSOrderRetained = true;
|
14268
15088
|
for (var _i = 0; _i < inputSamples.length; _i++) {
|
14269
|
-
if (inputSamples[_i].dts > firstPTS) {
|
15089
|
+
if (inputSamples[_i].dts > firstPTS && isPTSOrderRetained) {
|
14270
15090
|
break;
|
14271
15091
|
}
|
15092
|
+
var prevPTS = inputSamples[_i].pts;
|
14272
15093
|
inputSamples[_i].dts -= delta;
|
14273
15094
|
inputSamples[_i].pts -= delta;
|
15095
|
+
|
15096
|
+
// check to see if this sample's PTS order has changed
|
15097
|
+
// relative to the next one
|
15098
|
+
if (_i < inputSamples.length - 1) {
|
15099
|
+
var nextSamplePTS = inputSamples[_i + 1].pts;
|
15100
|
+
var currentSamplePTS = inputSamples[_i].pts;
|
15101
|
+
var currentOrder = nextSamplePTS <= currentSamplePTS;
|
15102
|
+
var prevOrder = nextSamplePTS <= prevPTS;
|
15103
|
+
isPTSOrderRetained = currentOrder == prevOrder;
|
15104
|
+
}
|
14274
15105
|
}
|
14275
15106
|
}
|
14276
15107
|
logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
|
@@ -14418,7 +15249,7 @@
|
|
14418
15249
|
}
|
14419
15250
|
}
|
14420
15251
|
}
|
14421
|
-
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
15252
|
+
// next AVC/HEVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
14422
15253
|
mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
|
14423
15254
|
this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
|
14424
15255
|
this.videoSampleDuration = mp4SampleDuration;
|
@@ -14553,7 +15384,7 @@
|
|
14553
15384
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
14554
15385
|
for (var j = 0; j < missing; j++) {
|
14555
15386
|
var newStamp = Math.max(nextPts, 0);
|
14556
|
-
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15387
|
+
var fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
|
14557
15388
|
if (!fillFrame) {
|
14558
15389
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
14559
15390
|
fillFrame = sample.unit.subarray();
|
@@ -14681,7 +15512,7 @@
|
|
14681
15512
|
// samples count of this segment's duration
|
14682
15513
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
14683
15514
|
// silent frame
|
14684
|
-
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15515
|
+
var silentFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
|
14685
15516
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
14686
15517
|
// Can't remux if we can't generate a silent frame...
|
14687
15518
|
if (!silentFrame) {
|
@@ -15071,13 +15902,15 @@
|
|
15071
15902
|
duration = transmuxConfig.duration,
|
15072
15903
|
initSegmentData = transmuxConfig.initSegmentData;
|
15073
15904
|
var keyData = getEncryptionType(uintData, decryptdata);
|
15074
|
-
if (keyData && keyData.method
|
15905
|
+
if (keyData && isFullSegmentEncryption(keyData.method)) {
|
15075
15906
|
var decrypter = this.getDecrypter();
|
15907
|
+
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
15908
|
+
|
15076
15909
|
// Software decryption is synchronous; webCrypto is not
|
15077
15910
|
if (decrypter.isSync()) {
|
15078
15911
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
15079
15912
|
// data is handled in the flush() call
|
15080
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
15913
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode);
|
15081
15914
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
15082
15915
|
var loadingParts = chunkMeta.part > -1;
|
15083
15916
|
if (loadingParts) {
|
@@ -15089,7 +15922,7 @@
|
|
15089
15922
|
}
|
15090
15923
|
uintData = new Uint8Array(decryptedData);
|
15091
15924
|
} else {
|
15092
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
15925
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(function (decryptedData) {
|
15093
15926
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
15094
15927
|
// the decrypted data has been transmuxed
|
15095
15928
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -15710,7 +16543,7 @@
|
|
15710
16543
|
observer.on(Events.ERROR, forwardMessage);
|
15711
16544
|
|
15712
16545
|
// forward logger events to main thread
|
15713
|
-
var forwardWorkerLogs = function forwardWorkerLogs() {
|
16546
|
+
var forwardWorkerLogs = function forwardWorkerLogs(logger) {
|
15714
16547
|
var _loop = function _loop(logFn) {
|
15715
16548
|
var func = function func(message) {
|
15716
16549
|
forwardMessage('workerLog', {
|
@@ -15731,8 +16564,8 @@
|
|
15731
16564
|
{
|
15732
16565
|
var config = JSON.parse(data.config);
|
15733
16566
|
self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
|
15734
|
-
enableLogs(config.debug, data.id);
|
15735
|
-
forwardWorkerLogs();
|
16567
|
+
var logger = enableLogs(config.debug, data.id);
|
16568
|
+
forwardWorkerLogs(logger);
|
15736
16569
|
forwardMessage('init', null);
|
15737
16570
|
break;
|
15738
16571
|
}
|
@@ -15906,16 +16739,7 @@
|
|
15906
16739
|
this.observer = new EventEmitter();
|
15907
16740
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
15908
16741
|
this.observer.on(Events.ERROR, forwardMessage);
|
15909
|
-
var
|
15910
|
-
isTypeSupported: function isTypeSupported() {
|
15911
|
-
return false;
|
15912
|
-
}
|
15913
|
-
};
|
15914
|
-
var m2tsTypeSupported = {
|
15915
|
-
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
15916
|
-
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
15917
|
-
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
15918
|
-
};
|
16742
|
+
var m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
|
15919
16743
|
|
15920
16744
|
// navigator.vendor is not always available in Web Worker
|
15921
16745
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -16199,7 +17023,7 @@
|
|
16199
17023
|
_inheritsLoose(AudioStreamController, _BaseStreamController);
|
16200
17024
|
function AudioStreamController(hls, fragmentTracker, keyLoader) {
|
16201
17025
|
var _this;
|
16202
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
17026
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
|
16203
17027
|
_this.videoBuffer = null;
|
16204
17028
|
_this.videoTrackCC = -1;
|
16205
17029
|
_this.waitingVideoCC = -1;
|
@@ -16211,27 +17035,24 @@
|
|
16211
17035
|
_this.flushing = false;
|
16212
17036
|
_this.bufferFlushed = false;
|
16213
17037
|
_this.cachedTrackLoadedData = null;
|
16214
|
-
_this.
|
17038
|
+
_this.registerListeners();
|
16215
17039
|
return _this;
|
16216
17040
|
}
|
16217
17041
|
var _proto = AudioStreamController.prototype;
|
16218
17042
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
16219
|
-
this.
|
17043
|
+
this.unregisterListeners();
|
16220
17044
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
16221
17045
|
this.mainDetails = null;
|
16222
17046
|
this.bufferedTrack = null;
|
16223
17047
|
this.switchingTrack = null;
|
16224
17048
|
};
|
16225
|
-
_proto.
|
17049
|
+
_proto.registerListeners = function registerListeners() {
|
17050
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
16226
17051
|
var hls = this.hls;
|
16227
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16228
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16229
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
16230
17052
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16231
17053
|
hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16232
17054
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16233
17055
|
hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16234
|
-
hls.on(Events.ERROR, this.onError, this);
|
16235
17056
|
hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
|
16236
17057
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16237
17058
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -16239,16 +17060,16 @@
|
|
16239
17060
|
hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
|
16240
17061
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
16241
17062
|
};
|
16242
|
-
_proto.
|
17063
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
16243
17064
|
var hls = this.hls;
|
16244
|
-
hls
|
16245
|
-
|
16246
|
-
|
17065
|
+
if (!hls) {
|
17066
|
+
return;
|
17067
|
+
}
|
17068
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
16247
17069
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16248
17070
|
hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16249
17071
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16250
17072
|
hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16251
|
-
hls.off(Events.ERROR, this.onError, this);
|
16252
17073
|
hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
|
16253
17074
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16254
17075
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -16407,12 +17228,13 @@
|
|
16407
17228
|
trackId = this.trackId;
|
16408
17229
|
var config = hls.config;
|
16409
17230
|
|
16410
|
-
// 1. if
|
17231
|
+
// 1. if buffering is suspended
|
17232
|
+
// 2. if video not attached AND
|
16411
17233
|
// start fragment already requested OR start frag prefetch not enabled
|
16412
|
-
//
|
17234
|
+
// 3. if tracks or track not loaded and selected
|
16413
17235
|
// then exit loop
|
16414
17236
|
// => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
|
16415
|
-
if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
17237
|
+
if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
16416
17238
|
return;
|
16417
17239
|
}
|
16418
17240
|
var levelInfo = levels[trackId];
|
@@ -16941,7 +17763,7 @@
|
|
16941
17763
|
_inheritsLoose(AudioTrackController, _BasePlaylistControll);
|
16942
17764
|
function AudioTrackController(hls) {
|
16943
17765
|
var _this;
|
16944
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
17766
|
+
_this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
|
16945
17767
|
_this.tracks = [];
|
16946
17768
|
_this.groupIds = null;
|
16947
17769
|
_this.tracksInGroup = [];
|
@@ -17270,26 +18092,23 @@
|
|
17270
18092
|
_inheritsLoose(SubtitleStreamController, _BaseStreamController);
|
17271
18093
|
function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
|
17272
18094
|
var _this;
|
17273
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
18095
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
|
17274
18096
|
_this.currentTrackId = -1;
|
17275
18097
|
_this.tracksBuffered = [];
|
17276
18098
|
_this.mainDetails = null;
|
17277
|
-
_this.
|
18099
|
+
_this.registerListeners();
|
17278
18100
|
return _this;
|
17279
18101
|
}
|
17280
18102
|
var _proto = SubtitleStreamController.prototype;
|
17281
18103
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
17282
|
-
this.
|
18104
|
+
this.unregisterListeners();
|
17283
18105
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
17284
18106
|
this.mainDetails = null;
|
17285
18107
|
};
|
17286
|
-
_proto.
|
18108
|
+
_proto.registerListeners = function registerListeners() {
|
18109
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
17287
18110
|
var hls = this.hls;
|
17288
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17289
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17290
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17291
18111
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17292
|
-
hls.on(Events.ERROR, this.onError, this);
|
17293
18112
|
hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17294
18113
|
hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17295
18114
|
hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17297,13 +18116,10 @@
|
|
17297
18116
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
17298
18117
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
17299
18118
|
};
|
17300
|
-
_proto.
|
18119
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
18120
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
17301
18121
|
var hls = this.hls;
|
17302
|
-
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17303
|
-
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17304
|
-
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17305
18122
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17306
|
-
hls.off(Events.ERROR, this.onError, this);
|
17307
18123
|
hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17308
18124
|
hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17309
18125
|
hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17526,10 +18342,10 @@
|
|
17526
18342
|
return;
|
17527
18343
|
}
|
17528
18344
|
// check to see if the payload needs to be decrypted
|
17529
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method
|
18345
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
|
17530
18346
|
var startTime = performance.now();
|
17531
18347
|
// decrypt the subtitles
|
17532
|
-
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
18348
|
+
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
|
17533
18349
|
hls.trigger(Events.ERROR, {
|
17534
18350
|
type: ErrorTypes.MEDIA_ERROR,
|
17535
18351
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -17661,7 +18477,7 @@
|
|
17661
18477
|
_inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
|
17662
18478
|
function SubtitleTrackController(hls) {
|
17663
18479
|
var _this;
|
17664
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
18480
|
+
_this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
|
17665
18481
|
_this.media = null;
|
17666
18482
|
_this.tracks = [];
|
17667
18483
|
_this.groupIds = null;
|
@@ -17670,12 +18486,12 @@
|
|
17670
18486
|
_this.currentTrack = null;
|
17671
18487
|
_this.selectDefaultTrack = true;
|
17672
18488
|
_this.queuedDefaultTrack = -1;
|
17673
|
-
_this.asyncPollTrackChange = function () {
|
17674
|
-
return _this.pollTrackChange(0);
|
17675
|
-
};
|
17676
18489
|
_this.useTextTrackPolling = false;
|
17677
18490
|
_this.subtitlePollingInterval = -1;
|
17678
18491
|
_this._subtitleDisplay = true;
|
18492
|
+
_this.asyncPollTrackChange = function () {
|
18493
|
+
return _this.pollTrackChange(0);
|
18494
|
+
};
|
17679
18495
|
_this.onTextTracksChanged = function () {
|
17680
18496
|
if (!_this.useTextTrackPolling) {
|
17681
18497
|
self.clearInterval(_this.subtitlePollingInterval);
|
@@ -17711,6 +18527,7 @@
|
|
17711
18527
|
this.tracks.length = 0;
|
17712
18528
|
this.tracksInGroup.length = 0;
|
17713
18529
|
this.currentTrack = null;
|
18530
|
+
// @ts-ignore
|
17714
18531
|
this.onTextTracksChanged = this.asyncPollTrackChange = null;
|
17715
18532
|
_BasePlaylistControll.prototype.destroy.call(this);
|
17716
18533
|
};
|
@@ -18184,57 +19001,57 @@
|
|
18184
19001
|
}();
|
18185
19002
|
|
18186
19003
|
var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
|
18187
|
-
var BufferController = /*#__PURE__*/function () {
|
19004
|
+
var BufferController = /*#__PURE__*/function (_Logger) {
|
19005
|
+
_inheritsLoose(BufferController, _Logger);
|
18188
19006
|
function BufferController(hls) {
|
18189
|
-
var _this
|
19007
|
+
var _this;
|
19008
|
+
_this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
|
18190
19009
|
// The level details used to determine duration, target-duration and live
|
18191
|
-
|
19010
|
+
_this.details = null;
|
18192
19011
|
// cache the self generated object url to detect hijack of video tag
|
18193
|
-
|
19012
|
+
_this._objectUrl = null;
|
18194
19013
|
// A queue of buffer operations which require the SourceBuffer to not be updating upon execution
|
18195
|
-
|
19014
|
+
_this.operationQueue = void 0;
|
18196
19015
|
// References to event listeners for each SourceBuffer, so that they can be referenced for event removal
|
18197
|
-
|
18198
|
-
|
19016
|
+
_this.listeners = void 0;
|
19017
|
+
_this.hls = void 0;
|
18199
19018
|
// The number of BUFFER_CODEC events received before any sourceBuffers are created
|
18200
|
-
|
19019
|
+
_this.bufferCodecEventsExpected = 0;
|
18201
19020
|
// The total number of BUFFER_CODEC events received
|
18202
|
-
|
19021
|
+
_this._bufferCodecEventsTotal = 0;
|
18203
19022
|
// A reference to the attached media element
|
18204
|
-
|
19023
|
+
_this.media = null;
|
18205
19024
|
// A reference to the active media source
|
18206
|
-
|
19025
|
+
_this.mediaSource = null;
|
18207
19026
|
// Last MP3 audio chunk appended
|
18208
|
-
|
18209
|
-
|
19027
|
+
_this.lastMpegAudioChunk = null;
|
19028
|
+
_this.appendSource = void 0;
|
18210
19029
|
// counters
|
18211
|
-
|
19030
|
+
_this.appendErrors = {
|
18212
19031
|
audio: 0,
|
18213
19032
|
video: 0,
|
18214
19033
|
audiovideo: 0
|
18215
19034
|
};
|
18216
|
-
|
18217
|
-
|
18218
|
-
|
18219
|
-
|
18220
|
-
this.warn = void 0;
|
18221
|
-
this.error = void 0;
|
18222
|
-
this._onEndStreaming = function (event) {
|
19035
|
+
_this.tracks = {};
|
19036
|
+
_this.pendingTracks = {};
|
19037
|
+
_this.sourceBuffer = void 0;
|
19038
|
+
_this._onEndStreaming = function (event) {
|
18223
19039
|
if (!_this.hls) {
|
18224
19040
|
return;
|
18225
19041
|
}
|
18226
19042
|
_this.hls.pauseBuffering();
|
18227
19043
|
};
|
18228
|
-
|
19044
|
+
_this._onStartStreaming = function (event) {
|
18229
19045
|
if (!_this.hls) {
|
18230
19046
|
return;
|
18231
19047
|
}
|
18232
19048
|
_this.hls.resumeBuffering();
|
18233
19049
|
};
|
18234
19050
|
// Keep as arrow functions so that we can directly reference these functions directly as event listeners
|
18235
|
-
|
18236
|
-
var
|
18237
|
-
|
19051
|
+
_this._onMediaSourceOpen = function () {
|
19052
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
19053
|
+
media = _assertThisInitialize.media,
|
19054
|
+
mediaSource = _assertThisInitialize.mediaSource;
|
18238
19055
|
_this.log('Media source opened');
|
18239
19056
|
if (media) {
|
18240
19057
|
media.removeEventListener('emptied', _this._onMediaEmptied);
|
@@ -18250,27 +19067,25 @@
|
|
18250
19067
|
}
|
18251
19068
|
_this.checkPendingTracks();
|
18252
19069
|
};
|
18253
|
-
|
19070
|
+
_this._onMediaSourceClose = function () {
|
18254
19071
|
_this.log('Media source closed');
|
18255
19072
|
};
|
18256
|
-
|
19073
|
+
_this._onMediaSourceEnded = function () {
|
18257
19074
|
_this.log('Media source ended');
|
18258
19075
|
};
|
18259
|
-
|
18260
|
-
var
|
18261
|
-
|
19076
|
+
_this._onMediaEmptied = function () {
|
19077
|
+
var _assertThisInitialize2 = _assertThisInitialized(_this),
|
19078
|
+
mediaSrc = _assertThisInitialize2.mediaSrc,
|
19079
|
+
_objectUrl = _assertThisInitialize2._objectUrl;
|
18262
19080
|
if (mediaSrc !== _objectUrl) {
|
18263
|
-
|
19081
|
+
_this.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
|
18264
19082
|
}
|
18265
19083
|
};
|
18266
|
-
|
18267
|
-
|
18268
|
-
|
18269
|
-
|
18270
|
-
|
18271
|
-
this.error = logger.error.bind(logger, logPrefix);
|
18272
|
-
this._initSourceBuffer();
|
18273
|
-
this.registerListeners();
|
19084
|
+
_this.hls = hls;
|
19085
|
+
_this.appendSource = hls.config.preferManagedMediaSource;
|
19086
|
+
_this._initSourceBuffer();
|
19087
|
+
_this.registerListeners();
|
19088
|
+
return _this;
|
18274
19089
|
}
|
18275
19090
|
var _proto = BufferController.prototype;
|
18276
19091
|
_proto.hasSourceTypes = function hasSourceTypes() {
|
@@ -18282,6 +19097,12 @@
|
|
18282
19097
|
this.lastMpegAudioChunk = null;
|
18283
19098
|
// @ts-ignore
|
18284
19099
|
this.hls = null;
|
19100
|
+
// @ts-ignore
|
19101
|
+
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
19102
|
+
// @ts-ignore
|
19103
|
+
this._onMediaSourceEnded = null;
|
19104
|
+
// @ts-ignore
|
19105
|
+
this._onStartStreaming = this._onEndStreaming = null;
|
18285
19106
|
};
|
18286
19107
|
_proto.registerListeners = function registerListeners() {
|
18287
19108
|
var hls = this.hls;
|
@@ -18439,6 +19260,7 @@
|
|
18439
19260
|
_this2.resetBuffer(type);
|
18440
19261
|
});
|
18441
19262
|
this._initSourceBuffer();
|
19263
|
+
this.hls.resumeBuffering();
|
18442
19264
|
};
|
18443
19265
|
_proto.resetBuffer = function resetBuffer(type) {
|
18444
19266
|
var sb = this.sourceBuffer[type];
|
@@ -19142,7 +19964,7 @@
|
|
19142
19964
|
}
|
19143
19965
|
}]);
|
19144
19966
|
return BufferController;
|
19145
|
-
}();
|
19967
|
+
}(Logger);
|
19146
19968
|
function removeSourceChildren(node) {
|
19147
19969
|
var sourceChildren = node.querySelectorAll('source');
|
19148
19970
|
[].slice.call(sourceChildren).forEach(function (source) {
|
@@ -21581,14 +22403,12 @@
|
|
21581
22403
|
this.cea608Parser1 = this.cea608Parser2 = undefined;
|
21582
22404
|
};
|
21583
22405
|
_proto.initCea608Parsers = function initCea608Parsers() {
|
21584
|
-
|
21585
|
-
|
21586
|
-
|
21587
|
-
|
21588
|
-
|
21589
|
-
|
21590
|
-
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21591
|
-
}
|
22406
|
+
var channel1 = new OutputFilter(this, 'textTrack1');
|
22407
|
+
var channel2 = new OutputFilter(this, 'textTrack2');
|
22408
|
+
var channel3 = new OutputFilter(this, 'textTrack3');
|
22409
|
+
var channel4 = new OutputFilter(this, 'textTrack4');
|
22410
|
+
this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
|
22411
|
+
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21592
22412
|
};
|
21593
22413
|
_proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
|
21594
22414
|
// skip cues which overlap more than 50% with previously parsed time ranges
|
@@ -21823,7 +22643,7 @@
|
|
21823
22643
|
return t.label;
|
21824
22644
|
});
|
21825
22645
|
if (unusedTextTracks.length) {
|
21826
|
-
logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
|
22646
|
+
this.hls.logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
|
21827
22647
|
}
|
21828
22648
|
}
|
21829
22649
|
} else if (this.tracks.length) {
|
@@ -21869,23 +22689,20 @@
|
|
21869
22689
|
return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
|
21870
22690
|
};
|
21871
22691
|
_proto.onFragLoading = function onFragLoading(event, data) {
|
21872
|
-
this.initCea608Parsers();
|
21873
|
-
var cea608Parser1 = this.cea608Parser1,
|
21874
|
-
cea608Parser2 = this.cea608Parser2,
|
21875
|
-
lastCc = this.lastCc,
|
21876
|
-
lastSn = this.lastSn,
|
21877
|
-
lastPartIndex = this.lastPartIndex;
|
21878
|
-
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
21879
|
-
return;
|
21880
|
-
}
|
21881
22692
|
// if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
|
21882
|
-
if (data.frag.type === PlaylistLevelType.MAIN) {
|
22693
|
+
if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
|
21883
22694
|
var _data$part$index, _data$part;
|
22695
|
+
var cea608Parser1 = this.cea608Parser1,
|
22696
|
+
cea608Parser2 = this.cea608Parser2,
|
22697
|
+
lastSn = this.lastSn;
|
22698
|
+
if (!cea608Parser1 || !cea608Parser2) {
|
22699
|
+
return;
|
22700
|
+
}
|
21884
22701
|
var _data$frag = data.frag,
|
21885
22702
|
cc = _data$frag.cc,
|
21886
22703
|
sn = _data$frag.sn;
|
21887
|
-
var partIndex = (_data$part$index =
|
21888
|
-
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
|
22704
|
+
var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
22705
|
+
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === this.lastPartIndex + 1 || cc === this.lastCc)) {
|
21889
22706
|
cea608Parser1.reset();
|
21890
22707
|
cea608Parser2.reset();
|
21891
22708
|
}
|
@@ -21941,7 +22758,7 @@
|
|
21941
22758
|
frag: frag
|
21942
22759
|
});
|
21943
22760
|
}, function (error) {
|
21944
|
-
logger.log("Failed to parse IMSC1: " + error);
|
22761
|
+
hls.logger.log("Failed to parse IMSC1: " + error);
|
21945
22762
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
21946
22763
|
success: false,
|
21947
22764
|
frag: frag,
|
@@ -21979,7 +22796,7 @@
|
|
21979
22796
|
_this5._fallbackToIMSC1(frag, payload);
|
21980
22797
|
}
|
21981
22798
|
// Something went wrong while parsing. Trigger event with success false.
|
21982
|
-
logger.log("Failed to parse VTT cue: " + error);
|
22799
|
+
hls.logger.log("Failed to parse VTT cue: " + error);
|
21983
22800
|
if (missingInitPTS && maxAvCC > frag.cc) {
|
21984
22801
|
return;
|
21985
22802
|
}
|
@@ -22041,10 +22858,7 @@
|
|
22041
22858
|
this.captionsTracks = {};
|
22042
22859
|
};
|
22043
22860
|
_proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
|
22044
|
-
this.
|
22045
|
-
var cea608Parser1 = this.cea608Parser1,
|
22046
|
-
cea608Parser2 = this.cea608Parser2;
|
22047
|
-
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
22861
|
+
if (!this.enabled || !this.config.enableCEA708Captions) {
|
22048
22862
|
return;
|
22049
22863
|
}
|
22050
22864
|
var frag = data.frag,
|
@@ -22057,9 +22871,12 @@
|
|
22057
22871
|
for (var i = 0; i < samples.length; i++) {
|
22058
22872
|
var ccBytes = samples[i].bytes;
|
22059
22873
|
if (ccBytes) {
|
22874
|
+
if (!this.cea608Parser1) {
|
22875
|
+
this.initCea608Parsers();
|
22876
|
+
}
|
22060
22877
|
var ccdatas = this.extractCea608Data(ccBytes);
|
22061
|
-
cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22062
|
-
cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22878
|
+
this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22879
|
+
this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22063
22880
|
}
|
22064
22881
|
}
|
22065
22882
|
};
|
@@ -22251,7 +23068,7 @@
|
|
22251
23068
|
var hls = this.hls;
|
22252
23069
|
var maxLevel = this.getMaxLevel(levels.length - 1);
|
22253
23070
|
if (maxLevel !== this.autoLevelCapping) {
|
22254
|
-
logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
23071
|
+
hls.logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
22255
23072
|
}
|
22256
23073
|
hls.autoLevelCapping = maxLevel;
|
22257
23074
|
if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
|
@@ -22441,10 +23258,10 @@
|
|
22441
23258
|
totalDroppedFrames: droppedFrames
|
22442
23259
|
});
|
22443
23260
|
if (droppedFPS > 0) {
|
22444
|
-
// logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
23261
|
+
// hls.logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
22445
23262
|
if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
|
22446
23263
|
var currentLevel = hls.currentLevel;
|
22447
|
-
logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
23264
|
+
hls.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
22448
23265
|
if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
|
22449
23266
|
currentLevel = currentLevel - 1;
|
22450
23267
|
hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
|
@@ -22477,7 +23294,6 @@
|
|
22477
23294
|
return FPSController;
|
22478
23295
|
}();
|
22479
23296
|
|
22480
|
-
var LOGGER_PREFIX = '[eme]';
|
22481
23297
|
/**
|
22482
23298
|
* Controller to deal with encrypted media extensions (EME)
|
22483
23299
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
|
@@ -22485,26 +23301,122 @@
|
|
22485
23301
|
* @class
|
22486
23302
|
* @constructor
|
22487
23303
|
*/
|
22488
|
-
var EMEController = /*#__PURE__*/function () {
|
23304
|
+
var EMEController = /*#__PURE__*/function (_Logger) {
|
23305
|
+
_inheritsLoose(EMEController, _Logger);
|
22489
23306
|
function EMEController(hls) {
|
22490
|
-
|
22491
|
-
this.
|
22492
|
-
|
22493
|
-
|
22494
|
-
|
22495
|
-
|
22496
|
-
|
22497
|
-
|
22498
|
-
|
22499
|
-
|
22500
|
-
|
22501
|
-
|
22502
|
-
|
22503
|
-
|
22504
|
-
|
22505
|
-
|
22506
|
-
|
22507
|
-
|
23307
|
+
var _this;
|
23308
|
+
_this = _Logger.call(this, 'eme', hls.logger) || this;
|
23309
|
+
_this.hls = void 0;
|
23310
|
+
_this.config = void 0;
|
23311
|
+
_this.media = null;
|
23312
|
+
_this.keyFormatPromise = null;
|
23313
|
+
_this.keySystemAccessPromises = {};
|
23314
|
+
_this._requestLicenseFailureCount = 0;
|
23315
|
+
_this.mediaKeySessions = [];
|
23316
|
+
_this.keyIdToKeySessionPromise = {};
|
23317
|
+
_this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
23318
|
+
_this.onMediaEncrypted = function (event) {
|
23319
|
+
var initDataType = event.initDataType,
|
23320
|
+
initData = event.initData;
|
23321
|
+
_this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
23322
|
+
|
23323
|
+
// Ignore event when initData is null
|
23324
|
+
if (initData === null) {
|
23325
|
+
return;
|
23326
|
+
}
|
23327
|
+
var keyId;
|
23328
|
+
var keySystemDomain;
|
23329
|
+
if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
23330
|
+
// Match sinf keyId to playlist skd://keyId=
|
23331
|
+
var json = bin2str(new Uint8Array(initData));
|
23332
|
+
try {
|
23333
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
23334
|
+
var tenc = parseSinf(new Uint8Array(sinf));
|
23335
|
+
if (!tenc) {
|
23336
|
+
return;
|
23337
|
+
}
|
23338
|
+
keyId = tenc.subarray(8, 24);
|
23339
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
23340
|
+
} catch (error) {
|
23341
|
+
_this.warn('Failed to parse sinf "encrypted" event message initData');
|
23342
|
+
return;
|
23343
|
+
}
|
23344
|
+
} else {
|
23345
|
+
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
23346
|
+
var psshInfo = parsePssh(initData);
|
23347
|
+
if (psshInfo === null) {
|
23348
|
+
return;
|
23349
|
+
}
|
23350
|
+
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
23351
|
+
keyId = psshInfo.data.subarray(8, 24);
|
23352
|
+
}
|
23353
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
23354
|
+
}
|
23355
|
+
if (!keySystemDomain || !keyId) {
|
23356
|
+
return;
|
23357
|
+
}
|
23358
|
+
var keyIdHex = Hex.hexDump(keyId);
|
23359
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
23360
|
+
keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
|
23361
|
+
mediaKeySessions = _assertThisInitialize.mediaKeySessions;
|
23362
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
23363
|
+
var _loop = function _loop() {
|
23364
|
+
// Match playlist key
|
23365
|
+
var keyContext = mediaKeySessions[i];
|
23366
|
+
var decryptdata = keyContext.decryptdata;
|
23367
|
+
if (decryptdata.pssh || !decryptdata.keyId) {
|
23368
|
+
return 0; // continue
|
23369
|
+
}
|
23370
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
23371
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
23372
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
23373
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
23374
|
+
decryptdata.pssh = new Uint8Array(initData);
|
23375
|
+
decryptdata.keyId = keyId;
|
23376
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
23377
|
+
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
23378
|
+
});
|
23379
|
+
return 1; // break
|
23380
|
+
}
|
23381
|
+
},
|
23382
|
+
_ret;
|
23383
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
23384
|
+
_ret = _loop();
|
23385
|
+
if (_ret === 0) continue;
|
23386
|
+
if (_ret === 1) break;
|
23387
|
+
}
|
23388
|
+
if (!keySessionContextPromise) {
|
23389
|
+
// Clear-lead key (not encountered in playlist)
|
23390
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
23391
|
+
var _keySystemToKeySystem;
|
23392
|
+
var keySystem = _ref.keySystem,
|
23393
|
+
mediaKeys = _ref.mediaKeys;
|
23394
|
+
_this.throwIfDestroyed();
|
23395
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
23396
|
+
decryptdata.pssh = new Uint8Array(initData);
|
23397
|
+
decryptdata.keyId = keyId;
|
23398
|
+
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23399
|
+
_this.throwIfDestroyed();
|
23400
|
+
var keySessionContext = _this.createMediaKeySessionContext({
|
23401
|
+
decryptdata: decryptdata,
|
23402
|
+
keySystem: keySystem,
|
23403
|
+
mediaKeys: mediaKeys
|
23404
|
+
});
|
23405
|
+
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
23406
|
+
});
|
23407
|
+
});
|
23408
|
+
}
|
23409
|
+
keySessionContextPromise.catch(function (error) {
|
23410
|
+
return _this.handleError(error);
|
23411
|
+
});
|
23412
|
+
};
|
23413
|
+
_this.onWaitingForKey = function (event) {
|
23414
|
+
_this.log("\"" + event.type + "\" event");
|
23415
|
+
};
|
23416
|
+
_this.hls = hls;
|
23417
|
+
_this.config = hls.config;
|
23418
|
+
_this.registerListeners();
|
23419
|
+
return _this;
|
22508
23420
|
}
|
22509
23421
|
var _proto = EMEController.prototype;
|
22510
23422
|
_proto.destroy = function destroy() {
|
@@ -22516,9 +23428,9 @@
|
|
22516
23428
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
22517
23429
|
config.drmSystems = config.drmSystemOptions = {};
|
22518
23430
|
// @ts-ignore
|
22519
|
-
this.hls = this.
|
23431
|
+
this.hls = this.config = this.keyIdToKeySessionPromise = null;
|
22520
23432
|
// @ts-ignore
|
22521
|
-
this.
|
23433
|
+
this.onMediaEncrypted = this.onWaitingForKey = null;
|
22522
23434
|
};
|
22523
23435
|
_proto.registerListeners = function registerListeners() {
|
22524
23436
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -22557,7 +23469,7 @@
|
|
22557
23469
|
}
|
22558
23470
|
};
|
22559
23471
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
22560
|
-
var
|
23472
|
+
var _this2 = this;
|
22561
23473
|
var levels = this.hls.levels;
|
22562
23474
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
22563
23475
|
return !!value && a.indexOf(value) === i;
|
@@ -22574,7 +23486,7 @@
|
|
22574
23486
|
return new Promise(function (resolve, reject) {
|
22575
23487
|
var attempt = function attempt(keySystems) {
|
22576
23488
|
var keySystem = keySystems.shift();
|
22577
|
-
|
23489
|
+
_this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
22578
23490
|
return resolve({
|
22579
23491
|
keySystem: keySystem,
|
22580
23492
|
mediaKeys: mediaKeys
|
@@ -22609,7 +23521,7 @@
|
|
22609
23521
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
22610
23522
|
};
|
22611
23523
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
22612
|
-
var
|
23524
|
+
var _this3 = this;
|
22613
23525
|
// This can throw, but is caught in event handler callpath
|
22614
23526
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
22615
23527
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -22621,23 +23533,23 @@
|
|
22621
23533
|
keySystemAccess: keySystemAccess
|
22622
23534
|
};
|
22623
23535
|
keySystemAccess.catch(function (error) {
|
22624
|
-
|
23536
|
+
_this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
22625
23537
|
});
|
22626
23538
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
22627
|
-
|
22628
|
-
var certificateRequest =
|
22629
|
-
|
23539
|
+
_this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
23540
|
+
var certificateRequest = _this3.fetchServerCertificate(keySystem);
|
23541
|
+
_this3.log("Create media-keys for \"" + keySystem + "\"");
|
22630
23542
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
22631
|
-
|
23543
|
+
_this3.log("Media-keys created for \"" + keySystem + "\"");
|
22632
23544
|
return certificateRequest.then(function (certificate) {
|
22633
23545
|
if (certificate) {
|
22634
|
-
return
|
23546
|
+
return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
22635
23547
|
}
|
22636
23548
|
return mediaKeys;
|
22637
23549
|
});
|
22638
23550
|
});
|
22639
23551
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
22640
|
-
|
23552
|
+
_this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
22641
23553
|
});
|
22642
23554
|
return _keySystemAccessPromises.mediaKeys;
|
22643
23555
|
});
|
@@ -22646,10 +23558,10 @@
|
|
22646
23558
|
return keySystemAccessPromises.mediaKeys;
|
22647
23559
|
});
|
22648
23560
|
};
|
22649
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
22650
|
-
var decryptdata =
|
22651
|
-
keySystem =
|
22652
|
-
mediaKeys =
|
23561
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
|
23562
|
+
var decryptdata = _ref2.decryptdata,
|
23563
|
+
keySystem = _ref2.keySystem,
|
23564
|
+
mediaKeys = _ref2.mediaKeys;
|
22653
23565
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
22654
23566
|
var mediaKeysSession = mediaKeys.createSession();
|
22655
23567
|
var mediaKeySessionContext = {
|
@@ -22698,14 +23610,14 @@
|
|
22698
23610
|
return this.keyFormatPromise;
|
22699
23611
|
};
|
22700
23612
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
22701
|
-
var
|
23613
|
+
var _this4 = this;
|
22702
23614
|
return new Promise(function (resolve, reject) {
|
22703
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
23615
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
|
22704
23616
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
22705
23617
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
22706
23618
|
});
|
22707
|
-
return
|
22708
|
-
var keySystem =
|
23619
|
+
return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
|
23620
|
+
var keySystem = _ref3.keySystem;
|
22709
23621
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
22710
23622
|
if (keySystemFormat) {
|
22711
23623
|
resolve(keySystemFormat);
|
@@ -22716,31 +23628,31 @@
|
|
22716
23628
|
});
|
22717
23629
|
};
|
22718
23630
|
_proto.loadKey = function loadKey(data) {
|
22719
|
-
var
|
23631
|
+
var _this5 = this;
|
22720
23632
|
var decryptdata = data.keyInfo.decryptdata;
|
22721
23633
|
var keyId = this.getKeyIdString(decryptdata);
|
22722
23634
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
22723
23635
|
this.log("Starting session for key " + keyDetails);
|
22724
23636
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
22725
23637
|
if (!keySessionContextPromise) {
|
22726
|
-
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (
|
22727
|
-
var keySystem =
|
22728
|
-
mediaKeys =
|
22729
|
-
|
22730
|
-
|
22731
|
-
return
|
22732
|
-
|
22733
|
-
var keySessionContext =
|
23638
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
|
23639
|
+
var keySystem = _ref4.keySystem,
|
23640
|
+
mediaKeys = _ref4.mediaKeys;
|
23641
|
+
_this5.throwIfDestroyed();
|
23642
|
+
_this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
23643
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23644
|
+
_this5.throwIfDestroyed();
|
23645
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22734
23646
|
keySystem: keySystem,
|
22735
23647
|
mediaKeys: mediaKeys,
|
22736
23648
|
decryptdata: decryptdata
|
22737
23649
|
});
|
22738
23650
|
var scheme = 'cenc';
|
22739
|
-
return
|
23651
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
22740
23652
|
});
|
22741
23653
|
});
|
22742
23654
|
keySessionContextPromise.catch(function (error) {
|
22743
|
-
return
|
23655
|
+
return _this5.handleError(error);
|
22744
23656
|
});
|
22745
23657
|
}
|
22746
23658
|
return keySessionContextPromise;
|
@@ -22766,128 +23678,30 @@
|
|
22766
23678
|
});
|
22767
23679
|
}
|
22768
23680
|
};
|
22769
|
-
_proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
|
22770
|
-
var keyId = this.getKeyIdString(decryptdata);
|
22771
|
-
var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
|
22772
|
-
if (!mediaKeySessionContext) {
|
22773
|
-
var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
|
22774
|
-
var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
|
22775
|
-
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22776
|
-
}
|
22777
|
-
return mediaKeySessionContext;
|
22778
|
-
};
|
22779
|
-
_proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
|
22780
|
-
if (!keySystemsToAttempt.length) {
|
22781
|
-
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
22782
|
-
}
|
22783
|
-
if (keySystemsToAttempt.length === 0) {
|
22784
|
-
throw new EMEKeyError({
|
22785
|
-
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
22786
|
-
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
22787
|
-
fatal: true
|
22788
|
-
}, "Missing key-system license configuration options " + JSON.stringify({
|
22789
|
-
drmSystems: this.config.drmSystems
|
22790
|
-
}));
|
22791
|
-
}
|
22792
|
-
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22793
|
-
};
|
22794
|
-
_proto._onMediaEncrypted = function _onMediaEncrypted(event) {
|
22795
|
-
var _this5 = this;
|
22796
|
-
var initDataType = event.initDataType,
|
22797
|
-
initData = event.initData;
|
22798
|
-
this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
22799
|
-
|
22800
|
-
// Ignore event when initData is null
|
22801
|
-
if (initData === null) {
|
22802
|
-
return;
|
22803
|
-
}
|
22804
|
-
var keyId;
|
22805
|
-
var keySystemDomain;
|
22806
|
-
if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22807
|
-
// Match sinf keyId to playlist skd://keyId=
|
22808
|
-
var json = bin2str(new Uint8Array(initData));
|
22809
|
-
try {
|
22810
|
-
var sinf = base64Decode(JSON.parse(json).sinf);
|
22811
|
-
var tenc = parseSinf(new Uint8Array(sinf));
|
22812
|
-
if (!tenc) {
|
22813
|
-
return;
|
22814
|
-
}
|
22815
|
-
keyId = tenc.subarray(8, 24);
|
22816
|
-
keySystemDomain = KeySystems.FAIRPLAY;
|
22817
|
-
} catch (error) {
|
22818
|
-
this.warn('Failed to parse sinf "encrypted" event message initData');
|
22819
|
-
return;
|
22820
|
-
}
|
22821
|
-
} else {
|
22822
|
-
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22823
|
-
var psshInfo = parsePssh(initData);
|
22824
|
-
if (psshInfo === null) {
|
22825
|
-
return;
|
22826
|
-
}
|
22827
|
-
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22828
|
-
keyId = psshInfo.data.subarray(8, 24);
|
22829
|
-
}
|
22830
|
-
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22831
|
-
}
|
22832
|
-
if (!keySystemDomain || !keyId) {
|
22833
|
-
return;
|
22834
|
-
}
|
22835
|
-
var keyIdHex = Hex.hexDump(keyId);
|
22836
|
-
var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
|
22837
|
-
mediaKeySessions = this.mediaKeySessions;
|
22838
|
-
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22839
|
-
var _loop = function _loop() {
|
22840
|
-
// Match playlist key
|
22841
|
-
var keyContext = mediaKeySessions[i];
|
22842
|
-
var decryptdata = keyContext.decryptdata;
|
22843
|
-
if (decryptdata.pssh || !decryptdata.keyId) {
|
22844
|
-
return 0; // continue
|
22845
|
-
}
|
22846
|
-
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22847
|
-
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22848
|
-
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22849
|
-
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22850
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22851
|
-
decryptdata.keyId = keyId;
|
22852
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22853
|
-
return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22854
|
-
});
|
22855
|
-
return 1; // break
|
22856
|
-
}
|
22857
|
-
},
|
22858
|
-
_ret;
|
22859
|
-
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22860
|
-
_ret = _loop();
|
22861
|
-
if (_ret === 0) continue;
|
22862
|
-
if (_ret === 1) break;
|
22863
|
-
}
|
22864
|
-
if (!keySessionContextPromise) {
|
22865
|
-
// Clear-lead key (not encountered in playlist)
|
22866
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
|
22867
|
-
var _keySystemToKeySystem;
|
22868
|
-
var keySystem = _ref4.keySystem,
|
22869
|
-
mediaKeys = _ref4.mediaKeys;
|
22870
|
-
_this5.throwIfDestroyed();
|
22871
|
-
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22872
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22873
|
-
decryptdata.keyId = keyId;
|
22874
|
-
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22875
|
-
_this5.throwIfDestroyed();
|
22876
|
-
var keySessionContext = _this5.createMediaKeySessionContext({
|
22877
|
-
decryptdata: decryptdata,
|
22878
|
-
keySystem: keySystem,
|
22879
|
-
mediaKeys: mediaKeys
|
22880
|
-
});
|
22881
|
-
return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22882
|
-
});
|
22883
|
-
});
|
23681
|
+
_proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
|
23682
|
+
var keyId = this.getKeyIdString(decryptdata);
|
23683
|
+
var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
|
23684
|
+
if (!mediaKeySessionContext) {
|
23685
|
+
var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
|
23686
|
+
var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
|
23687
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22884
23688
|
}
|
22885
|
-
|
22886
|
-
return _this5.handleError(error);
|
22887
|
-
});
|
23689
|
+
return mediaKeySessionContext;
|
22888
23690
|
};
|
22889
|
-
_proto.
|
22890
|
-
|
23691
|
+
_proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
|
23692
|
+
if (!keySystemsToAttempt.length) {
|
23693
|
+
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
23694
|
+
}
|
23695
|
+
if (keySystemsToAttempt.length === 0) {
|
23696
|
+
throw new EMEKeyError({
|
23697
|
+
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
23698
|
+
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
23699
|
+
fatal: true
|
23700
|
+
}, "Missing key-system license configuration options " + JSON.stringify({
|
23701
|
+
drmSystems: this.config.drmSystems
|
23702
|
+
}));
|
23703
|
+
}
|
23704
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22891
23705
|
};
|
22892
23706
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
22893
23707
|
var _this6 = this;
|
@@ -23344,7 +24158,7 @@
|
|
23344
24158
|
}
|
23345
24159
|
};
|
23346
24160
|
return EMEController;
|
23347
|
-
}();
|
24161
|
+
}(Logger);
|
23348
24162
|
EMEController.CDMCleanupPromise = void 0;
|
23349
24163
|
var EMEKeyError = /*#__PURE__*/function (_Error) {
|
23350
24164
|
_inheritsLoose(EMEKeyError, _Error);
|
@@ -23492,18 +24306,6 @@
|
|
23492
24306
|
this.params = params;
|
23493
24307
|
};
|
23494
24308
|
|
23495
|
-
/**
|
23496
|
-
* A class to represent structured field tokens when `Symbol` is not available.
|
23497
|
-
*
|
23498
|
-
* @group Structured Field
|
23499
|
-
*
|
23500
|
-
* @beta
|
23501
|
-
*/
|
23502
|
-
var SfToken = function SfToken(description) {
|
23503
|
-
this.description = void 0;
|
23504
|
-
this.description = description;
|
23505
|
-
};
|
23506
|
-
|
23507
24309
|
var DICT = 'Dict';
|
23508
24310
|
|
23509
24311
|
function format(value) {
|
@@ -23527,29 +24329,25 @@
|
|
23527
24329
|
});
|
23528
24330
|
}
|
23529
24331
|
|
23530
|
-
|
23531
|
-
|
23532
|
-
var BOOLEAN = 'Boolean';
|
23533
|
-
|
23534
|
-
var BYTES = 'Byte Sequence';
|
23535
|
-
|
23536
|
-
var DECIMAL = 'Decimal';
|
23537
|
-
|
23538
|
-
var INTEGER = 'Integer';
|
23539
|
-
|
23540
|
-
function isInvalidInt(value) {
|
23541
|
-
return value < -999999999999999 || 999999999999999 < value;
|
24332
|
+
function serializeError(src, type, cause) {
|
24333
|
+
return throwError('serialize', src, type, cause);
|
23542
24334
|
}
|
23543
24335
|
|
23544
|
-
|
23545
|
-
|
23546
|
-
|
24336
|
+
/**
|
24337
|
+
* A class to represent structured field tokens when `Symbol` is not available.
|
24338
|
+
*
|
24339
|
+
* @group Structured Field
|
24340
|
+
*
|
24341
|
+
* @beta
|
24342
|
+
*/
|
24343
|
+
var SfToken = function SfToken(description) {
|
24344
|
+
this.description = void 0;
|
24345
|
+
this.description = description;
|
24346
|
+
};
|
23547
24347
|
|
23548
|
-
var
|
24348
|
+
var BARE_ITEM = 'Bare Item';
|
23549
24349
|
|
23550
|
-
|
23551
|
-
return throwError('serialize', src, type, cause);
|
23552
|
-
}
|
24350
|
+
var BOOLEAN = 'Boolean';
|
23553
24351
|
|
23554
24352
|
// 4.1.9. Serializing a Boolean
|
23555
24353
|
//
|
@@ -23588,6 +24386,8 @@
|
|
23588
24386
|
return btoa(String.fromCharCode.apply(String, binary));
|
23589
24387
|
}
|
23590
24388
|
|
24389
|
+
var BYTES = 'Byte Sequence';
|
24390
|
+
|
23591
24391
|
// 4.1.8. Serializing a Byte Sequence
|
23592
24392
|
//
|
23593
24393
|
// Given a Byte Sequence as input_bytes, return an ASCII string suitable
|
@@ -23619,6 +24419,12 @@
|
|
23619
24419
|
return ":" + base64encode(value) + ":";
|
23620
24420
|
}
|
23621
24421
|
|
24422
|
+
var INTEGER = 'Integer';
|
24423
|
+
|
24424
|
+
function isInvalidInt(value) {
|
24425
|
+
return value < -999999999999999 || 999999999999999 < value;
|
24426
|
+
}
|
24427
|
+
|
23622
24428
|
// 4.1.4. Serializing an Integer
|
23623
24429
|
//
|
23624
24430
|
// Given an Integer as input_integer, return an ASCII string suitable
|
@@ -23684,6 +24490,8 @@
|
|
23684
24490
|
}
|
23685
24491
|
}
|
23686
24492
|
|
24493
|
+
var DECIMAL = 'Decimal';
|
24494
|
+
|
23687
24495
|
// 4.1.5. Serializing a Decimal
|
23688
24496
|
//
|
23689
24497
|
// Given a decimal number as input_decimal, return an ASCII string
|
@@ -23729,6 +24537,8 @@
|
|
23729
24537
|
|
23730
24538
|
var STRING = 'String';
|
23731
24539
|
|
24540
|
+
var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
|
24541
|
+
|
23732
24542
|
// 4.1.6. Serializing a String
|
23733
24543
|
//
|
23734
24544
|
// Given a String as input_string, return an ASCII string suitable for
|
@@ -23764,6 +24574,8 @@
|
|
23764
24574
|
return symbol.description || symbol.toString().slice(7, -1);
|
23765
24575
|
}
|
23766
24576
|
|
24577
|
+
var TOKEN = 'Token';
|
24578
|
+
|
23767
24579
|
function serializeToken(token) {
|
23768
24580
|
var value = symbolToStr(token);
|
23769
24581
|
if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
|
@@ -23831,6 +24643,8 @@
|
|
23831
24643
|
}
|
23832
24644
|
}
|
23833
24645
|
|
24646
|
+
var KEY = 'Key';
|
24647
|
+
|
23834
24648
|
// 4.1.1.3. Serializing a Key
|
23835
24649
|
//
|
23836
24650
|
// Given a key as input_key, return an ASCII string suitable for use in
|
@@ -24082,36 +24896,6 @@
|
|
24082
24896
|
return toPath.join('/');
|
24083
24897
|
}
|
24084
24898
|
|
24085
|
-
/**
|
24086
|
-
* Generate a random v4 UUID
|
24087
|
-
*
|
24088
|
-
* @returns A random v4 UUID
|
24089
|
-
*
|
24090
|
-
* @group Utils
|
24091
|
-
*
|
24092
|
-
* @beta
|
24093
|
-
*/
|
24094
|
-
function uuid() {
|
24095
|
-
try {
|
24096
|
-
return crypto.randomUUID();
|
24097
|
-
} catch (error) {
|
24098
|
-
try {
|
24099
|
-
var url = URL.createObjectURL(new Blob());
|
24100
|
-
var _uuid = url.toString();
|
24101
|
-
URL.revokeObjectURL(url);
|
24102
|
-
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
24103
|
-
} catch (error) {
|
24104
|
-
var dt = new Date().getTime();
|
24105
|
-
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
24106
|
-
var r = (dt + Math.random() * 16) % 16 | 0;
|
24107
|
-
dt = Math.floor(dt / 16);
|
24108
|
-
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
24109
|
-
});
|
24110
|
-
return _uuid2;
|
24111
|
-
}
|
24112
|
-
}
|
24113
|
-
}
|
24114
|
-
|
24115
24899
|
var toRounded = function toRounded(value) {
|
24116
24900
|
return Math.round(value);
|
24117
24901
|
};
|
@@ -24356,6 +25140,36 @@
|
|
24356
25140
|
return "" + url + separator + query;
|
24357
25141
|
}
|
24358
25142
|
|
25143
|
+
/**
|
25144
|
+
* Generate a random v4 UUID
|
25145
|
+
*
|
25146
|
+
* @returns A random v4 UUID
|
25147
|
+
*
|
25148
|
+
* @group Utils
|
25149
|
+
*
|
25150
|
+
* @beta
|
25151
|
+
*/
|
25152
|
+
function uuid() {
|
25153
|
+
try {
|
25154
|
+
return crypto.randomUUID();
|
25155
|
+
} catch (error) {
|
25156
|
+
try {
|
25157
|
+
var url = URL.createObjectURL(new Blob());
|
25158
|
+
var _uuid = url.toString();
|
25159
|
+
URL.revokeObjectURL(url);
|
25160
|
+
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
25161
|
+
} catch (error) {
|
25162
|
+
var dt = new Date().getTime();
|
25163
|
+
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
25164
|
+
var r = (dt + Math.random() * 16) % 16 | 0;
|
25165
|
+
dt = Math.floor(dt / 16);
|
25166
|
+
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
25167
|
+
});
|
25168
|
+
return _uuid2;
|
25169
|
+
}
|
25170
|
+
}
|
25171
|
+
}
|
25172
|
+
|
24359
25173
|
/**
|
24360
25174
|
* Controller to deal with Common Media Client Data (CMCD)
|
24361
25175
|
* @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
|
@@ -24420,6 +25234,12 @@
|
|
24420
25234
|
data.tb = _this.getTopBandwidth(ot) / 1000;
|
24421
25235
|
data.bl = _this.getBufferLength(ot);
|
24422
25236
|
}
|
25237
|
+
var next = _this.getNextFrag(fragment);
|
25238
|
+
if (next) {
|
25239
|
+
if (next.url && next.url !== fragment.url) {
|
25240
|
+
data.nor = next.url;
|
25241
|
+
}
|
25242
|
+
}
|
24423
25243
|
_this.apply(context, data);
|
24424
25244
|
} catch (error) {
|
24425
25245
|
logger.warn('Could not generate segment CMCD data.', error);
|
@@ -24514,7 +25334,7 @@
|
|
24514
25334
|
data.su = this.buffering;
|
24515
25335
|
}
|
24516
25336
|
|
24517
|
-
// TODO: Implement rtp, nrr,
|
25337
|
+
// TODO: Implement rtp, nrr, dl
|
24518
25338
|
|
24519
25339
|
var includeKeys = this.includeKeys;
|
24520
25340
|
if (includeKeys) {
|
@@ -24523,18 +25343,31 @@
|
|
24523
25343
|
return acc;
|
24524
25344
|
}, {});
|
24525
25345
|
}
|
25346
|
+
var options = {
|
25347
|
+
baseUrl: context.url
|
25348
|
+
};
|
24526
25349
|
if (this.useHeaders) {
|
24527
25350
|
if (!context.headers) {
|
24528
25351
|
context.headers = {};
|
24529
25352
|
}
|
24530
|
-
appendCmcdHeaders(context.headers, data);
|
25353
|
+
appendCmcdHeaders(context.headers, data, options);
|
24531
25354
|
} else {
|
24532
|
-
context.url = appendCmcdQuery(context.url, data);
|
25355
|
+
context.url = appendCmcdQuery(context.url, data, options);
|
24533
25356
|
}
|
24534
25357
|
};
|
25358
|
+
_proto.getNextFrag = function getNextFrag(fragment) {
|
25359
|
+
var _this$hls$levels$frag;
|
25360
|
+
var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
|
25361
|
+
if (levelDetails) {
|
25362
|
+
var index = fragment.sn - levelDetails.startSN;
|
25363
|
+
return levelDetails.fragments[index + 1];
|
25364
|
+
}
|
25365
|
+
return undefined;
|
25366
|
+
}
|
25367
|
+
|
24535
25368
|
/**
|
24536
25369
|
* The CMCD object type.
|
24537
|
-
|
25370
|
+
*/;
|
24538
25371
|
_proto.getObjectType = function getObjectType(fragment) {
|
24539
25372
|
var type = fragment.type;
|
24540
25373
|
if (type === 'subtitle') {
|
@@ -24670,26 +25503,28 @@
|
|
24670
25503
|
}();
|
24671
25504
|
|
24672
25505
|
var PATHWAY_PENALTY_DURATION_MS = 300000;
|
24673
|
-
var ContentSteeringController = /*#__PURE__*/function () {
|
25506
|
+
var ContentSteeringController = /*#__PURE__*/function (_Logger) {
|
25507
|
+
_inheritsLoose(ContentSteeringController, _Logger);
|
24674
25508
|
function ContentSteeringController(hls) {
|
24675
|
-
|
24676
|
-
this.
|
24677
|
-
|
24678
|
-
|
24679
|
-
|
24680
|
-
|
24681
|
-
|
24682
|
-
|
24683
|
-
|
24684
|
-
|
24685
|
-
|
24686
|
-
|
24687
|
-
|
24688
|
-
|
24689
|
-
|
24690
|
-
|
24691
|
-
|
24692
|
-
|
25509
|
+
var _this;
|
25510
|
+
_this = _Logger.call(this, 'content-steering', hls.logger) || this;
|
25511
|
+
_this.hls = void 0;
|
25512
|
+
_this.loader = null;
|
25513
|
+
_this.uri = null;
|
25514
|
+
_this.pathwayId = '.';
|
25515
|
+
_this.pathwayPriority = null;
|
25516
|
+
_this.timeToLoad = 300;
|
25517
|
+
_this.reloadTimer = -1;
|
25518
|
+
_this.updated = 0;
|
25519
|
+
_this.started = false;
|
25520
|
+
_this.enabled = true;
|
25521
|
+
_this.levels = null;
|
25522
|
+
_this.audioTracks = null;
|
25523
|
+
_this.subtitleTracks = null;
|
25524
|
+
_this.penalizedPathways = {};
|
25525
|
+
_this.hls = hls;
|
25526
|
+
_this.registerListeners();
|
25527
|
+
return _this;
|
24693
25528
|
}
|
24694
25529
|
var _proto = ContentSteeringController.prototype;
|
24695
25530
|
_proto.registerListeners = function registerListeners() {
|
@@ -24810,7 +25645,7 @@
|
|
24810
25645
|
errorAction.resolved = this.pathwayId !== errorPathway;
|
24811
25646
|
}
|
24812
25647
|
if (!errorAction.resolved) {
|
24813
|
-
|
25648
|
+
this.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));
|
24814
25649
|
}
|
24815
25650
|
}
|
24816
25651
|
};
|
@@ -24890,7 +25725,7 @@
|
|
24890
25725
|
return defaultPathway;
|
24891
25726
|
};
|
24892
25727
|
_proto.clonePathways = function clonePathways(pathwayClones) {
|
24893
|
-
var
|
25728
|
+
var _this2 = this;
|
24894
25729
|
var levels = this.levels;
|
24895
25730
|
if (!levels) {
|
24896
25731
|
return;
|
@@ -24906,7 +25741,7 @@
|
|
24906
25741
|
})) {
|
24907
25742
|
return;
|
24908
25743
|
}
|
24909
|
-
var clonedVariants =
|
25744
|
+
var clonedVariants = _this2.getLevelsForPathway(baseId).map(function (baseLevel) {
|
24910
25745
|
var attributes = new AttrList(baseLevel.attrs);
|
24911
25746
|
attributes['PATHWAY-ID'] = cloneId;
|
24912
25747
|
var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
|
@@ -24943,12 +25778,12 @@
|
|
24943
25778
|
return clonedLevel;
|
24944
25779
|
});
|
24945
25780
|
levels.push.apply(levels, clonedVariants);
|
24946
|
-
cloneRenditionGroups(
|
24947
|
-
cloneRenditionGroups(
|
25781
|
+
cloneRenditionGroups(_this2.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
|
25782
|
+
cloneRenditionGroups(_this2.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
|
24948
25783
|
});
|
24949
25784
|
};
|
24950
25785
|
_proto.loadSteeringManifest = function loadSteeringManifest(uri) {
|
24951
|
-
var
|
25786
|
+
var _this3 = this;
|
24952
25787
|
var config = this.hls.config;
|
24953
25788
|
var Loader = config.loader;
|
24954
25789
|
if (this.loader) {
|
@@ -24983,87 +25818,87 @@
|
|
24983
25818
|
};
|
24984
25819
|
var callbacks = {
|
24985
25820
|
onSuccess: function onSuccess(response, stats, context, networkDetails) {
|
24986
|
-
|
25821
|
+
_this3.log("Loaded steering manifest: \"" + url + "\"");
|
24987
25822
|
var steeringData = response.data;
|
24988
|
-
if (steeringData.VERSION !== 1) {
|
24989
|
-
|
25823
|
+
if ((steeringData == null ? void 0 : steeringData.VERSION) !== 1) {
|
25824
|
+
_this3.log("Steering VERSION " + steeringData.VERSION + " not supported!");
|
24990
25825
|
return;
|
24991
25826
|
}
|
24992
|
-
|
24993
|
-
|
25827
|
+
_this3.updated = performance.now();
|
25828
|
+
_this3.timeToLoad = steeringData.TTL;
|
24994
25829
|
var reloadUri = steeringData['RELOAD-URI'],
|
24995
25830
|
pathwayClones = steeringData['PATHWAY-CLONES'],
|
24996
25831
|
pathwayPriority = steeringData['PATHWAY-PRIORITY'];
|
24997
25832
|
if (reloadUri) {
|
24998
25833
|
try {
|
24999
|
-
|
25834
|
+
_this3.uri = new self.URL(reloadUri, url).href;
|
25000
25835
|
} catch (error) {
|
25001
|
-
|
25002
|
-
|
25836
|
+
_this3.enabled = false;
|
25837
|
+
_this3.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
|
25003
25838
|
return;
|
25004
25839
|
}
|
25005
25840
|
}
|
25006
|
-
|
25841
|
+
_this3.scheduleRefresh(_this3.uri || context.url);
|
25007
25842
|
if (pathwayClones) {
|
25008
|
-
|
25843
|
+
_this3.clonePathways(pathwayClones);
|
25009
25844
|
}
|
25010
25845
|
var loadedSteeringData = {
|
25011
25846
|
steeringManifest: steeringData,
|
25012
25847
|
url: url.toString()
|
25013
25848
|
};
|
25014
|
-
|
25849
|
+
_this3.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
|
25015
25850
|
if (pathwayPriority) {
|
25016
|
-
|
25851
|
+
_this3.updatePathwayPriority(pathwayPriority);
|
25017
25852
|
}
|
25018
25853
|
},
|
25019
25854
|
onError: function onError(error, context, networkDetails, stats) {
|
25020
|
-
|
25021
|
-
|
25855
|
+
_this3.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
|
25856
|
+
_this3.stopLoad();
|
25022
25857
|
if (error.code === 410) {
|
25023
|
-
|
25024
|
-
|
25858
|
+
_this3.enabled = false;
|
25859
|
+
_this3.log("Steering manifest " + context.url + " no longer available");
|
25025
25860
|
return;
|
25026
25861
|
}
|
25027
|
-
var ttl =
|
25862
|
+
var ttl = _this3.timeToLoad * 1000;
|
25028
25863
|
if (error.code === 429) {
|
25029
|
-
var loader =
|
25864
|
+
var loader = _this3.loader;
|
25030
25865
|
if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
|
25031
25866
|
var retryAfter = loader.getResponseHeader('Retry-After');
|
25032
25867
|
if (retryAfter) {
|
25033
25868
|
ttl = parseFloat(retryAfter) * 1000;
|
25034
25869
|
}
|
25035
25870
|
}
|
25036
|
-
|
25871
|
+
_this3.log("Steering manifest " + context.url + " rate limited");
|
25037
25872
|
return;
|
25038
25873
|
}
|
25039
|
-
|
25874
|
+
_this3.scheduleRefresh(_this3.uri || context.url, ttl);
|
25040
25875
|
},
|
25041
25876
|
onTimeout: function onTimeout(stats, context, networkDetails) {
|
25042
|
-
|
25043
|
-
|
25877
|
+
_this3.log("Timeout loading steering manifest (" + context.url + ")");
|
25878
|
+
_this3.scheduleRefresh(_this3.uri || context.url);
|
25044
25879
|
}
|
25045
25880
|
};
|
25046
25881
|
this.log("Requesting steering manifest: " + url);
|
25047
25882
|
this.loader.load(context, loaderConfig, callbacks);
|
25048
25883
|
};
|
25049
25884
|
_proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
|
25050
|
-
var
|
25885
|
+
var _this4 = this;
|
25051
25886
|
if (ttlMs === void 0) {
|
25052
25887
|
ttlMs = this.timeToLoad * 1000;
|
25053
25888
|
}
|
25054
25889
|
this.clearTimeout();
|
25055
25890
|
this.reloadTimer = self.setTimeout(function () {
|
25056
|
-
var
|
25057
|
-
var media = (
|
25891
|
+
var _this4$hls;
|
25892
|
+
var media = (_this4$hls = _this4.hls) == null ? void 0 : _this4$hls.media;
|
25058
25893
|
if (media && !media.ended) {
|
25059
|
-
|
25894
|
+
_this4.loadSteeringManifest(uri);
|
25060
25895
|
return;
|
25061
25896
|
}
|
25062
|
-
|
25897
|
+
_this4.scheduleRefresh(uri, _this4.timeToLoad * 1000);
|
25063
25898
|
}, ttlMs);
|
25064
25899
|
};
|
25065
25900
|
return ContentSteeringController;
|
25066
|
-
}();
|
25901
|
+
}(Logger);
|
25067
25902
|
function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
|
25068
25903
|
if (!tracks) {
|
25069
25904
|
return;
|
@@ -25963,7 +26798,7 @@
|
|
25963
26798
|
/**
|
25964
26799
|
* @ignore
|
25965
26800
|
*/
|
25966
|
-
function mergeConfig(defaultConfig, userConfig) {
|
26801
|
+
function mergeConfig(defaultConfig, userConfig, logger) {
|
25967
26802
|
if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
|
25968
26803
|
throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
|
25969
26804
|
}
|
@@ -26033,7 +26868,7 @@
|
|
26033
26868
|
/**
|
26034
26869
|
* @ignore
|
26035
26870
|
*/
|
26036
|
-
function enableStreamingMode(config) {
|
26871
|
+
function enableStreamingMode(config, logger) {
|
26037
26872
|
var currentLoader = config.loader;
|
26038
26873
|
if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
|
26039
26874
|
// If a developer has configured their own loader, respect that choice
|
@@ -26050,12 +26885,11 @@
|
|
26050
26885
|
}
|
26051
26886
|
}
|
26052
26887
|
|
26053
|
-
var chromeOrFirefox;
|
26054
26888
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
26055
26889
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
26056
26890
|
function LevelController(hls, contentSteeringController) {
|
26057
26891
|
var _this;
|
26058
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
26892
|
+
_this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
|
26059
26893
|
_this._levels = [];
|
26060
26894
|
_this._firstLevel = -1;
|
26061
26895
|
_this._maxAutoLevel = -1;
|
@@ -26124,21 +26958,13 @@
|
|
26124
26958
|
var videoCodecFound = false;
|
26125
26959
|
var audioCodecFound = false;
|
26126
26960
|
data.levels.forEach(function (levelParsed) {
|
26127
|
-
var
|
26961
|
+
var _videoCodec;
|
26128
26962
|
var attributes = levelParsed.attrs;
|
26129
|
-
|
26130
|
-
// erase audio codec info if browser does not support mp4a.40.34.
|
26131
|
-
// demuxer will autodetect codec and fallback to mpeg/audio
|
26132
26963
|
var audioCodec = levelParsed.audioCodec,
|
26133
26964
|
videoCodec = levelParsed.videoCodec;
|
26134
|
-
if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
|
26135
|
-
chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
|
26136
|
-
if (chromeOrFirefox) {
|
26137
|
-
levelParsed.audioCodec = audioCodec = undefined;
|
26138
|
-
}
|
26139
|
-
}
|
26140
26965
|
if (audioCodec) {
|
26141
|
-
|
26966
|
+
// Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
|
26967
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
26142
26968
|
}
|
26143
26969
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
26144
26970
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -26746,6 +27572,8 @@
|
|
26746
27572
|
}
|
26747
27573
|
return this.loadKeyEME(keyInfo, frag);
|
26748
27574
|
case 'AES-128':
|
27575
|
+
case 'AES-256':
|
27576
|
+
case 'AES-256-CTR':
|
26749
27577
|
return this.loadKeyHTTP(keyInfo, frag);
|
26750
27578
|
default:
|
26751
27579
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -26885,21 +27713,26 @@
|
|
26885
27713
|
var MAX_START_GAP_JUMP = 2.0;
|
26886
27714
|
var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
|
26887
27715
|
var SKIP_BUFFER_RANGE_START = 0.05;
|
26888
|
-
var GapController = /*#__PURE__*/function () {
|
27716
|
+
var GapController = /*#__PURE__*/function (_Logger) {
|
27717
|
+
_inheritsLoose(GapController, _Logger);
|
26889
27718
|
function GapController(config, media, fragmentTracker, hls) {
|
26890
|
-
|
26891
|
-
this.
|
26892
|
-
|
26893
|
-
|
26894
|
-
|
26895
|
-
|
26896
|
-
|
26897
|
-
|
26898
|
-
|
26899
|
-
|
26900
|
-
|
26901
|
-
|
26902
|
-
|
27719
|
+
var _this;
|
27720
|
+
_this = _Logger.call(this, 'gap-controller', hls.logger) || this;
|
27721
|
+
_this.config = void 0;
|
27722
|
+
_this.media = null;
|
27723
|
+
_this.fragmentTracker = void 0;
|
27724
|
+
_this.hls = void 0;
|
27725
|
+
_this.nudgeRetry = 0;
|
27726
|
+
_this.stallReported = false;
|
27727
|
+
_this.stalled = null;
|
27728
|
+
_this.moved = false;
|
27729
|
+
_this.seeking = false;
|
27730
|
+
_this.ended = 0;
|
27731
|
+
_this.config = config;
|
27732
|
+
_this.media = media;
|
27733
|
+
_this.fragmentTracker = fragmentTracker;
|
27734
|
+
_this.hls = hls;
|
27735
|
+
return _this;
|
26903
27736
|
}
|
26904
27737
|
var _proto = GapController.prototype;
|
26905
27738
|
_proto.destroy = function destroy() {
|
@@ -26914,7 +27747,7 @@
|
|
26914
27747
|
*
|
26915
27748
|
* @param lastCurrentTime - Previously read playhead position
|
26916
27749
|
*/;
|
26917
|
-
_proto.poll = function poll(lastCurrentTime, activeFrag) {
|
27750
|
+
_proto.poll = function poll(lastCurrentTime, activeFrag, levelDetails, state) {
|
26918
27751
|
var config = this.config,
|
26919
27752
|
media = this.media,
|
26920
27753
|
stalled = this.stalled;
|
@@ -26929,6 +27762,7 @@
|
|
26929
27762
|
|
26930
27763
|
// The playhead is moving, no-op
|
26931
27764
|
if (currentTime !== lastCurrentTime) {
|
27765
|
+
this.ended = 0;
|
26932
27766
|
this.moved = true;
|
26933
27767
|
if (!seeking) {
|
26934
27768
|
this.nudgeRetry = 0;
|
@@ -26937,7 +27771,7 @@
|
|
26937
27771
|
// The playhead is now moving, but was previously stalled
|
26938
27772
|
if (this.stallReported) {
|
26939
27773
|
var _stalledDuration = self.performance.now() - stalled;
|
26940
|
-
|
27774
|
+
this.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
|
26941
27775
|
this.stallReported = false;
|
26942
27776
|
}
|
26943
27777
|
this.stalled = null;
|
@@ -26973,7 +27807,6 @@
|
|
26973
27807
|
// Skip start gaps if we haven't played, but the last poll detected the start of a stall
|
26974
27808
|
// The addition poll gives the browser a chance to jump the gap for us
|
26975
27809
|
if (!this.moved && this.stalled !== null) {
|
26976
|
-
var _level$details;
|
26977
27810
|
// There is no playable buffer (seeked, waiting for buffer)
|
26978
27811
|
var isBuffered = bufferInfo.len > 0;
|
26979
27812
|
if (!isBuffered && !nextStart) {
|
@@ -26985,9 +27818,8 @@
|
|
26985
27818
|
// When joining a live stream with audio tracks, account for live playlist window sliding by allowing
|
26986
27819
|
// a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
|
26987
27820
|
// that begins over 1 target duration after the video start position.
|
26988
|
-
var
|
26989
|
-
var
|
26990
|
-
var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP;
|
27821
|
+
var isLive = !!(levelDetails != null && levelDetails.live);
|
27822
|
+
var maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
|
26991
27823
|
var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
|
26992
27824
|
if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
|
26993
27825
|
if (!media.paused) {
|
@@ -27005,6 +27837,17 @@
|
|
27005
27837
|
}
|
27006
27838
|
var stalledDuration = tnow - stalled;
|
27007
27839
|
if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
|
27840
|
+
// Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
|
27841
|
+
if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
|
27842
|
+
if (stalledDuration < 1000 || this.ended) {
|
27843
|
+
return;
|
27844
|
+
}
|
27845
|
+
this.ended = currentTime;
|
27846
|
+
this.hls.trigger(Events.MEDIA_ENDED, {
|
27847
|
+
stalled: true
|
27848
|
+
});
|
27849
|
+
return;
|
27850
|
+
}
|
27008
27851
|
// Report stalling after trying to fix
|
27009
27852
|
this._reportStall(bufferInfo);
|
27010
27853
|
if (!this.media) {
|
@@ -27046,7 +27889,7 @@
|
|
27046
27889
|
// needs to cross some sort of threshold covering all source-buffers content
|
27047
27890
|
// to start playing properly.
|
27048
27891
|
if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
|
27049
|
-
|
27892
|
+
this.warn('Trying to nudge playhead over buffer-hole');
|
27050
27893
|
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
|
27051
27894
|
// We only try to jump the hole if it's under the configured size
|
27052
27895
|
// Reset stalled so to rearm watchdog timer
|
@@ -27068,7 +27911,7 @@
|
|
27068
27911
|
// Report stalled error once
|
27069
27912
|
this.stallReported = true;
|
27070
27913
|
var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
|
27071
|
-
|
27914
|
+
this.warn(error.message);
|
27072
27915
|
hls.trigger(Events.ERROR, {
|
27073
27916
|
type: ErrorTypes.MEDIA_ERROR,
|
27074
27917
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27132,7 +27975,7 @@
|
|
27132
27975
|
}
|
27133
27976
|
}
|
27134
27977
|
var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
|
27135
|
-
|
27978
|
+
this.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
|
27136
27979
|
this.moved = true;
|
27137
27980
|
this.stalled = null;
|
27138
27981
|
media.currentTime = targetTime;
|
@@ -27171,7 +28014,7 @@
|
|
27171
28014
|
var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
|
27172
28015
|
// playback stalled in buffered area ... let's nudge currentTime to try to overcome this
|
27173
28016
|
var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
|
27174
|
-
|
28017
|
+
this.warn(error.message);
|
27175
28018
|
media.currentTime = targetTime;
|
27176
28019
|
hls.trigger(Events.ERROR, {
|
27177
28020
|
type: ErrorTypes.MEDIA_ERROR,
|
@@ -27181,7 +28024,7 @@
|
|
27181
28024
|
});
|
27182
28025
|
} else {
|
27183
28026
|
var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
|
27184
|
-
|
28027
|
+
this.error(_error.message);
|
27185
28028
|
hls.trigger(Events.ERROR, {
|
27186
28029
|
type: ErrorTypes.MEDIA_ERROR,
|
27187
28030
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27191,14 +28034,14 @@
|
|
27191
28034
|
}
|
27192
28035
|
};
|
27193
28036
|
return GapController;
|
27194
|
-
}();
|
28037
|
+
}(Logger);
|
27195
28038
|
|
27196
28039
|
var TICK_INTERVAL = 100; // how often to tick in ms
|
27197
28040
|
var StreamController = /*#__PURE__*/function (_BaseStreamController) {
|
27198
28041
|
_inheritsLoose(StreamController, _BaseStreamController);
|
27199
28042
|
function StreamController(hls, fragmentTracker, keyLoader) {
|
27200
28043
|
var _this;
|
27201
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
28044
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
|
27202
28045
|
_this.audioCodecSwap = false;
|
27203
28046
|
_this.gapController = null;
|
27204
28047
|
_this.level = -1;
|
@@ -27206,27 +28049,43 @@
|
|
27206
28049
|
_this.altAudio = false;
|
27207
28050
|
_this.audioOnly = false;
|
27208
28051
|
_this.fragPlaying = null;
|
27209
|
-
_this.onvplaying = null;
|
27210
|
-
_this.onvseeked = null;
|
27211
28052
|
_this.fragLastKbps = 0;
|
27212
28053
|
_this.couldBacktrack = false;
|
27213
28054
|
_this.backtrackFragment = null;
|
27214
28055
|
_this.audioCodecSwitch = false;
|
27215
28056
|
_this.videoBuffer = null;
|
27216
|
-
_this.
|
28057
|
+
_this.onMediaPlaying = function () {
|
28058
|
+
// tick to speed up FRAG_CHANGED triggering
|
28059
|
+
_this.tick();
|
28060
|
+
};
|
28061
|
+
_this.onMediaSeeked = function () {
|
28062
|
+
var media = _this.media;
|
28063
|
+
var currentTime = media ? media.currentTime : null;
|
28064
|
+
if (isFiniteNumber(currentTime)) {
|
28065
|
+
_this.log("Media seeked to " + currentTime.toFixed(3));
|
28066
|
+
}
|
28067
|
+
|
28068
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
28069
|
+
var bufferInfo = _this.getMainFwdBufferInfo();
|
28070
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
28071
|
+
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
28072
|
+
return;
|
28073
|
+
}
|
28074
|
+
|
28075
|
+
// tick to speed up FRAG_CHANGED triggering
|
28076
|
+
_this.tick();
|
28077
|
+
};
|
28078
|
+
_this.registerListeners();
|
27217
28079
|
return _this;
|
27218
28080
|
}
|
27219
28081
|
var _proto = StreamController.prototype;
|
27220
|
-
_proto.
|
28082
|
+
_proto.registerListeners = function registerListeners() {
|
28083
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
27221
28084
|
var hls = this.hls;
|
27222
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27223
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27224
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
27225
28085
|
hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27226
28086
|
hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
|
27227
28087
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27228
28088
|
hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27229
|
-
hls.on(Events.ERROR, this.onError, this);
|
27230
28089
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27231
28090
|
hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27232
28091
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27234,15 +28093,12 @@
|
|
27234
28093
|
hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
|
27235
28094
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27236
28095
|
};
|
27237
|
-
_proto.
|
28096
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
28097
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
27238
28098
|
var hls = this.hls;
|
27239
|
-
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27240
|
-
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27241
|
-
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
27242
28099
|
hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27243
28100
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27244
28101
|
hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27245
|
-
hls.off(Events.ERROR, this.onError, this);
|
27246
28102
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27247
28103
|
hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27248
28104
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27251,7 +28107,9 @@
|
|
27251
28107
|
hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27252
28108
|
};
|
27253
28109
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
27254
|
-
|
28110
|
+
// @ts-ignore
|
28111
|
+
this.onMediaPlaying = this.onMediaSeeked = null;
|
28112
|
+
this.unregisterListeners();
|
27255
28113
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
27256
28114
|
};
|
27257
28115
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -27361,7 +28219,7 @@
|
|
27361
28219
|
if (this.altAudio && this.audioOnly) {
|
27362
28220
|
return;
|
27363
28221
|
}
|
27364
|
-
if (!(levels != null && levels[level])) {
|
28222
|
+
if (!this.buffering || !(levels != null && levels[level])) {
|
27365
28223
|
return;
|
27366
28224
|
}
|
27367
28225
|
var levelInfo = levels[level];
|
@@ -27567,18 +28425,15 @@
|
|
27567
28425
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
27568
28426
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
27569
28427
|
var media = data.media;
|
27570
|
-
|
27571
|
-
|
27572
|
-
media.addEventListener('playing', this.onvplaying);
|
27573
|
-
media.addEventListener('seeked', this.onvseeked);
|
28428
|
+
media.addEventListener('playing', this.onMediaPlaying);
|
28429
|
+
media.addEventListener('seeked', this.onMediaSeeked);
|
27574
28430
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
27575
28431
|
};
|
27576
28432
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
27577
28433
|
var media = this.media;
|
27578
|
-
if (media
|
27579
|
-
media.removeEventListener('playing', this.
|
27580
|
-
media.removeEventListener('seeked', this.
|
27581
|
-
this.onvplaying = this.onvseeked = null;
|
28434
|
+
if (media) {
|
28435
|
+
media.removeEventListener('playing', this.onMediaPlaying);
|
28436
|
+
media.removeEventListener('seeked', this.onMediaSeeked);
|
27582
28437
|
this.videoBuffer = null;
|
27583
28438
|
}
|
27584
28439
|
this.fragPlaying = null;
|
@@ -27588,27 +28443,6 @@
|
|
27588
28443
|
}
|
27589
28444
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
27590
28445
|
};
|
27591
|
-
_proto.onMediaPlaying = function onMediaPlaying() {
|
27592
|
-
// tick to speed up FRAG_CHANGED triggering
|
27593
|
-
this.tick();
|
27594
|
-
};
|
27595
|
-
_proto.onMediaSeeked = function onMediaSeeked() {
|
27596
|
-
var media = this.media;
|
27597
|
-
var currentTime = media ? media.currentTime : null;
|
27598
|
-
if (isFiniteNumber(currentTime)) {
|
27599
|
-
this.log("Media seeked to " + currentTime.toFixed(3));
|
27600
|
-
}
|
27601
|
-
|
27602
|
-
// If seeked was issued before buffer was appended do not tick immediately
|
27603
|
-
var bufferInfo = this.getMainFwdBufferInfo();
|
27604
|
-
if (bufferInfo === null || bufferInfo.len === 0) {
|
27605
|
-
this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27606
|
-
return;
|
27607
|
-
}
|
27608
|
-
|
27609
|
-
// tick to speed up FRAG_CHANGED triggering
|
27610
|
-
this.tick();
|
27611
|
-
};
|
27612
28446
|
_proto.onManifestLoading = function onManifestLoading() {
|
27613
28447
|
// reset buffer on manifest loading
|
27614
28448
|
this.log('Trigger BUFFER_RESET');
|
@@ -27889,8 +28723,10 @@
|
|
27889
28723
|
}
|
27890
28724
|
if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
|
27891
28725
|
// Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
|
27892
|
-
var
|
27893
|
-
|
28726
|
+
var state = this.state;
|
28727
|
+
var activeFrag = state !== State.IDLE ? this.fragCurrent : null;
|
28728
|
+
var levelDetails = this.getLevelDetails();
|
28729
|
+
gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
|
27894
28730
|
}
|
27895
28731
|
this.lastCurrentTime = media.currentTime;
|
27896
28732
|
};
|
@@ -28355,9 +29191,12 @@
|
|
28355
29191
|
* The configuration object provided on player instantiation.
|
28356
29192
|
*/
|
28357
29193
|
this.userConfig = void 0;
|
29194
|
+
/**
|
29195
|
+
* The logger functions used by this player instance, configured on player instantiation.
|
29196
|
+
*/
|
29197
|
+
this.logger = void 0;
|
28358
29198
|
this.coreComponents = void 0;
|
28359
29199
|
this.networkControllers = void 0;
|
28360
|
-
this.started = false;
|
28361
29200
|
this._emitter = new EventEmitter();
|
28362
29201
|
this._autoLevelCapping = -1;
|
28363
29202
|
this._maxHdcpLevel = null;
|
@@ -28374,11 +29213,11 @@
|
|
28374
29213
|
this._media = null;
|
28375
29214
|
this.url = null;
|
28376
29215
|
this.triggeringException = void 0;
|
28377
|
-
enableLogs(userConfig.debug || false, 'Hls instance');
|
28378
|
-
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
|
29216
|
+
var logger = this.logger = enableLogs(userConfig.debug || false, 'Hls instance');
|
29217
|
+
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig, logger);
|
28379
29218
|
this.userConfig = userConfig;
|
28380
29219
|
if (config.progressive) {
|
28381
|
-
enableStreamingMode(config);
|
29220
|
+
enableStreamingMode(config, logger);
|
28382
29221
|
}
|
28383
29222
|
|
28384
29223
|
// core controllers and network loaders
|
@@ -28486,7 +29325,7 @@
|
|
28486
29325
|
try {
|
28487
29326
|
return this.emit(event, event, eventObject);
|
28488
29327
|
} catch (error) {
|
28489
|
-
logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
29328
|
+
this.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
28490
29329
|
// Prevent recursion in error event handlers that throw #5497
|
28491
29330
|
if (!this.triggeringException) {
|
28492
29331
|
this.triggeringException = true;
|
@@ -28512,7 +29351,7 @@
|
|
28512
29351
|
* Dispose of the instance
|
28513
29352
|
*/;
|
28514
29353
|
_proto.destroy = function destroy() {
|
28515
|
-
logger.log('destroy');
|
29354
|
+
this.logger.log('destroy');
|
28516
29355
|
this.trigger(Events.DESTROYING, undefined);
|
28517
29356
|
this.detachMedia();
|
28518
29357
|
this.removeAllListeners();
|
@@ -28537,7 +29376,7 @@
|
|
28537
29376
|
* Attaches Hls.js to a media element
|
28538
29377
|
*/;
|
28539
29378
|
_proto.attachMedia = function attachMedia(media) {
|
28540
|
-
logger.log('attachMedia');
|
29379
|
+
this.logger.log('attachMedia');
|
28541
29380
|
this._media = media;
|
28542
29381
|
this.trigger(Events.MEDIA_ATTACHING, {
|
28543
29382
|
media: media
|
@@ -28548,7 +29387,7 @@
|
|
28548
29387
|
* Detach Hls.js from the media
|
28549
29388
|
*/;
|
28550
29389
|
_proto.detachMedia = function detachMedia() {
|
28551
|
-
logger.log('detachMedia');
|
29390
|
+
this.logger.log('detachMedia');
|
28552
29391
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
28553
29392
|
this._media = null;
|
28554
29393
|
}
|
@@ -28565,7 +29404,7 @@
|
|
28565
29404
|
});
|
28566
29405
|
this._autoLevelCapping = -1;
|
28567
29406
|
this._maxHdcpLevel = null;
|
28568
|
-
logger.log("loadSource:" + loadingSource);
|
29407
|
+
this.logger.log("loadSource:" + loadingSource);
|
28569
29408
|
if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
|
28570
29409
|
this.detachMedia();
|
28571
29410
|
this.attachMedia(media);
|
@@ -28587,8 +29426,7 @@
|
|
28587
29426
|
if (startPosition === void 0) {
|
28588
29427
|
startPosition = -1;
|
28589
29428
|
}
|
28590
|
-
logger.log("startLoad(" + startPosition + ")");
|
28591
|
-
this.started = true;
|
29429
|
+
this.logger.log("startLoad(" + startPosition + ")");
|
28592
29430
|
this.networkControllers.forEach(function (controller) {
|
28593
29431
|
controller.startLoad(startPosition);
|
28594
29432
|
});
|
@@ -28598,34 +29436,31 @@
|
|
28598
29436
|
* Stop loading of any stream data.
|
28599
29437
|
*/;
|
28600
29438
|
_proto.stopLoad = function stopLoad() {
|
28601
|
-
logger.log('stopLoad');
|
28602
|
-
this.started = false;
|
29439
|
+
this.logger.log('stopLoad');
|
28603
29440
|
this.networkControllers.forEach(function (controller) {
|
28604
29441
|
controller.stopLoad();
|
28605
29442
|
});
|
28606
29443
|
}
|
28607
29444
|
|
28608
29445
|
/**
|
28609
|
-
* Resumes stream controller segment loading
|
29446
|
+
* Resumes stream controller segment loading after `pauseBuffering` has been called.
|
28610
29447
|
*/;
|
28611
29448
|
_proto.resumeBuffering = function resumeBuffering() {
|
28612
|
-
|
28613
|
-
|
28614
|
-
|
28615
|
-
|
28616
|
-
|
28617
|
-
});
|
28618
|
-
}
|
29449
|
+
this.networkControllers.forEach(function (controller) {
|
29450
|
+
if (controller.resumeBuffering) {
|
29451
|
+
controller.resumeBuffering();
|
29452
|
+
}
|
29453
|
+
});
|
28619
29454
|
}
|
28620
29455
|
|
28621
29456
|
/**
|
28622
|
-
*
|
29457
|
+
* Prevents stream controller from loading new segments until `resumeBuffering` is called.
|
28623
29458
|
* This allows for media buffering to be paused without interupting playlist loading.
|
28624
29459
|
*/;
|
28625
29460
|
_proto.pauseBuffering = function pauseBuffering() {
|
28626
29461
|
this.networkControllers.forEach(function (controller) {
|
28627
|
-
if (
|
28628
|
-
controller.
|
29462
|
+
if (controller.pauseBuffering) {
|
29463
|
+
controller.pauseBuffering();
|
28629
29464
|
}
|
28630
29465
|
});
|
28631
29466
|
}
|
@@ -28634,7 +29469,7 @@
|
|
28634
29469
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
28635
29470
|
*/;
|
28636
29471
|
_proto.swapAudioCodec = function swapAudioCodec() {
|
28637
|
-
logger.log('swapAudioCodec');
|
29472
|
+
this.logger.log('swapAudioCodec');
|
28638
29473
|
this.streamController.swapAudioCodec();
|
28639
29474
|
}
|
28640
29475
|
|
@@ -28645,7 +29480,7 @@
|
|
28645
29480
|
* Automatic recovery of media-errors by this process is configurable.
|
28646
29481
|
*/;
|
28647
29482
|
_proto.recoverMediaError = function recoverMediaError() {
|
28648
|
-
logger.log('recoverMediaError');
|
29483
|
+
this.logger.log('recoverMediaError');
|
28649
29484
|
var media = this._media;
|
28650
29485
|
this.detachMedia();
|
28651
29486
|
if (media) {
|
@@ -28700,7 +29535,7 @@
|
|
28700
29535
|
* 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.
|
28701
29536
|
*/,
|
28702
29537
|
set: function set(newLevel) {
|
28703
|
-
logger.log("set currentLevel:" + newLevel);
|
29538
|
+
this.logger.log("set currentLevel:" + newLevel);
|
28704
29539
|
this.levelController.manualLevel = newLevel;
|
28705
29540
|
this.streamController.immediateLevelSwitch();
|
28706
29541
|
}
|
@@ -28721,7 +29556,7 @@
|
|
28721
29556
|
* @param newLevel - Pass -1 for automatic level selection
|
28722
29557
|
*/,
|
28723
29558
|
set: function set(newLevel) {
|
28724
|
-
logger.log("set nextLevel:" + newLevel);
|
29559
|
+
this.logger.log("set nextLevel:" + newLevel);
|
28725
29560
|
this.levelController.manualLevel = newLevel;
|
28726
29561
|
this.streamController.nextLevelSwitch();
|
28727
29562
|
}
|
@@ -28742,7 +29577,7 @@
|
|
28742
29577
|
* @param newLevel - Pass -1 for automatic level selection
|
28743
29578
|
*/,
|
28744
29579
|
set: function set(newLevel) {
|
28745
|
-
logger.log("set loadLevel:" + newLevel);
|
29580
|
+
this.logger.log("set loadLevel:" + newLevel);
|
28746
29581
|
this.levelController.manualLevel = newLevel;
|
28747
29582
|
}
|
28748
29583
|
|
@@ -28777,7 +29612,7 @@
|
|
28777
29612
|
* Sets "first-level", see getter.
|
28778
29613
|
*/,
|
28779
29614
|
set: function set(newLevel) {
|
28780
|
-
logger.log("set firstLevel:" + newLevel);
|
29615
|
+
this.logger.log("set firstLevel:" + newLevel);
|
28781
29616
|
this.levelController.firstLevel = newLevel;
|
28782
29617
|
}
|
28783
29618
|
|
@@ -28804,7 +29639,7 @@
|
|
28804
29639
|
* (determined from download of first segment)
|
28805
29640
|
*/,
|
28806
29641
|
set: function set(newLevel) {
|
28807
|
-
logger.log("set startLevel:" + newLevel);
|
29642
|
+
this.logger.log("set startLevel:" + newLevel);
|
28808
29643
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
28809
29644
|
if (newLevel !== -1) {
|
28810
29645
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -28857,7 +29692,7 @@
|
|
28857
29692
|
*/
|
28858
29693
|
function set(newLevel) {
|
28859
29694
|
if (this._autoLevelCapping !== newLevel) {
|
28860
|
-
logger.log("set autoLevelCapping:" + newLevel);
|
29695
|
+
this.logger.log("set autoLevelCapping:" + newLevel);
|
28861
29696
|
this._autoLevelCapping = newLevel;
|
28862
29697
|
this.levelController.checkMaxAutoUpdated();
|
28863
29698
|
}
|
@@ -29182,7 +30017,7 @@
|
|
29182
30017
|
* Get the video-dev/hls.js package version.
|
29183
30018
|
*/
|
29184
30019
|
function get() {
|
29185
|
-
return "1.5.
|
30020
|
+
return "1.5.5-0.canary.9977";
|
29186
30021
|
}
|
29187
30022
|
}, {
|
29188
30023
|
key: "Events",
|