hls.js 1.5.4 → 1.5.5-0.canary.9978
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 +1935 -1094
- package/dist/hls.js.d.ts +63 -50
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +1059 -838
- 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 +846 -626
- 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 +1640 -814
- 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 +71 -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.9978");
|
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
|
-
|
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;
|
12015
12378
|
}
|
12016
|
-
var _proto =
|
12017
|
-
_proto.
|
12018
|
-
var
|
12019
|
-
var units = this.
|
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
|
+
}
|
12498
|
+
}
|
12499
|
+
if (!VideoSample) {
|
12500
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12118
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,21 @@
|
|
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
|
+
{
|
13281
|
+
this.videoParser = new HevcVideoParser();
|
13282
|
+
}
|
13283
|
+
break;
|
13284
|
+
}
|
13285
|
+
}
|
13286
|
+
if (this.videoParser !== null) {
|
13287
|
+
this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
|
13288
|
+
}
|
12567
13289
|
}
|
12568
13290
|
videoData = {
|
12569
13291
|
data: [],
|
@@ -12726,8 +13448,22 @@
|
|
12726
13448
|
// try to parse last PES packets
|
12727
13449
|
var pes;
|
12728
13450
|
if (videoData && (pes = parsePES(videoData))) {
|
12729
|
-
this.videoParser
|
12730
|
-
|
13451
|
+
if (this.videoParser === null) {
|
13452
|
+
switch (videoTrack.segmentCodec) {
|
13453
|
+
case 'avc':
|
13454
|
+
this.videoParser = new AvcVideoParser();
|
13455
|
+
break;
|
13456
|
+
case 'hevc':
|
13457
|
+
{
|
13458
|
+
this.videoParser = new HevcVideoParser();
|
13459
|
+
}
|
13460
|
+
break;
|
13461
|
+
}
|
13462
|
+
}
|
13463
|
+
if (this.videoParser !== null) {
|
13464
|
+
this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
|
13465
|
+
videoTrack.pesData = null;
|
13466
|
+
}
|
12731
13467
|
} else {
|
12732
13468
|
// either avcData null or PES truncated, keep it for next frag parsing
|
12733
13469
|
videoTrack.pesData = videoData;
|
@@ -13059,7 +13795,14 @@
|
|
13059
13795
|
logger.warn('Unsupported EC-3 in M2TS found');
|
13060
13796
|
break;
|
13061
13797
|
case 0x24:
|
13062
|
-
|
13798
|
+
// ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
|
13799
|
+
{
|
13800
|
+
if (result.videoPid === -1) {
|
13801
|
+
result.videoPid = pid;
|
13802
|
+
result.segmentVideoCodec = 'hevc';
|
13803
|
+
logger.log('HEVC in M2TS found');
|
13804
|
+
}
|
13805
|
+
}
|
13063
13806
|
break;
|
13064
13807
|
}
|
13065
13808
|
// move to the next table entry
|
@@ -13287,6 +14030,8 @@
|
|
13287
14030
|
avc1: [],
|
13288
14031
|
// codingname
|
13289
14032
|
avcC: [],
|
14033
|
+
hvc1: [],
|
14034
|
+
hvcC: [],
|
13290
14035
|
btrt: [],
|
13291
14036
|
dinf: [],
|
13292
14037
|
dref: [],
|
@@ -13714,8 +14459,10 @@
|
|
13714
14459
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
13715
14460
|
}
|
13716
14461
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
13717
|
-
} else {
|
14462
|
+
} else if (track.segmentCodec === 'avc') {
|
13718
14463
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
14464
|
+
} else {
|
14465
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.hvc1(track));
|
13719
14466
|
}
|
13720
14467
|
};
|
13721
14468
|
MP4.tkhd = function tkhd(track) {
|
@@ -13853,6 +14600,84 @@
|
|
13853
14600
|
var result = appendUint8Array(MP4.FTYP, movie);
|
13854
14601
|
return result;
|
13855
14602
|
};
|
14603
|
+
MP4.hvc1 = function hvc1(track) {
|
14604
|
+
var ps = track.params;
|
14605
|
+
var units = [track.vps, track.sps, track.pps];
|
14606
|
+
var NALuLengthSize = 4;
|
14607
|
+
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]);
|
14608
|
+
|
14609
|
+
// compute hvcC size in bytes
|
14610
|
+
var length = config.length;
|
14611
|
+
for (var i = 0; i < units.length; i += 1) {
|
14612
|
+
length += 3;
|
14613
|
+
for (var j = 0; j < units[i].length; j += 1) {
|
14614
|
+
length += 2 + units[i][j].length;
|
14615
|
+
}
|
14616
|
+
}
|
14617
|
+
var hvcC = new Uint8Array(length);
|
14618
|
+
hvcC.set(config, 0);
|
14619
|
+
length = config.length;
|
14620
|
+
// append parameter set units: one vps, one or more sps and pps
|
14621
|
+
var iMax = units.length - 1;
|
14622
|
+
for (var _i = 0; _i < units.length; _i += 1) {
|
14623
|
+
hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
|
14624
|
+
length += 3;
|
14625
|
+
for (var _j = 0; _j < units[_i].length; _j += 1) {
|
14626
|
+
hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
|
14627
|
+
length += 2;
|
14628
|
+
hvcC.set(units[_i][_j], length);
|
14629
|
+
length += units[_i][_j].length;
|
14630
|
+
}
|
14631
|
+
}
|
14632
|
+
var hvcc = MP4.box(MP4.types.hvcC, hvcC);
|
14633
|
+
var width = track.width;
|
14634
|
+
var height = track.height;
|
14635
|
+
var hSpacing = track.pixelRatio[0];
|
14636
|
+
var vSpacing = track.pixelRatio[1];
|
14637
|
+
return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
|
14638
|
+
// reserved
|
14639
|
+
0x00, 0x00, 0x00,
|
14640
|
+
// reserved
|
14641
|
+
0x00, 0x01,
|
14642
|
+
// data_reference_index
|
14643
|
+
0x00, 0x00,
|
14644
|
+
// pre_defined
|
14645
|
+
0x00, 0x00,
|
14646
|
+
// reserved
|
14647
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
14648
|
+
// pre_defined
|
14649
|
+
width >> 8 & 0xff, width & 0xff,
|
14650
|
+
// width
|
14651
|
+
height >> 8 & 0xff, height & 0xff,
|
14652
|
+
// height
|
14653
|
+
0x00, 0x48, 0x00, 0x00,
|
14654
|
+
// horizresolution
|
14655
|
+
0x00, 0x48, 0x00, 0x00,
|
14656
|
+
// vertresolution
|
14657
|
+
0x00, 0x00, 0x00, 0x00,
|
14658
|
+
// reserved
|
14659
|
+
0x00, 0x01,
|
14660
|
+
// frame_count
|
14661
|
+
0x12, 0x64, 0x61, 0x69, 0x6c,
|
14662
|
+
// dailymotion/hls.js
|
14663
|
+
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,
|
14664
|
+
// compressorname
|
14665
|
+
0x00, 0x18,
|
14666
|
+
// depth = 24
|
14667
|
+
0x11, 0x11]),
|
14668
|
+
// pre_defined = -1
|
14669
|
+
hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
|
14670
|
+
// bufferSizeDB
|
14671
|
+
0x00, 0x2d, 0xc6, 0xc0,
|
14672
|
+
// maxBitrate
|
14673
|
+
0x00, 0x2d, 0xc6, 0xc0])),
|
14674
|
+
// avgBitrate
|
14675
|
+
MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
|
14676
|
+
// hSpacing
|
14677
|
+
hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
|
14678
|
+
// vSpacing
|
14679
|
+
vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
|
14680
|
+
};
|
13856
14681
|
return MP4;
|
13857
14682
|
}();
|
13858
14683
|
MP4.types = void 0;
|
@@ -14254,9 +15079,9 @@
|
|
14254
15079
|
var foundOverlap = delta < -1;
|
14255
15080
|
if (foundHole || foundOverlap) {
|
14256
15081
|
if (foundHole) {
|
14257
|
-
logger.warn("
|
15082
|
+
logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
|
14258
15083
|
} else {
|
14259
|
-
logger.warn("
|
15084
|
+
logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
|
14260
15085
|
}
|
14261
15086
|
if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
|
14262
15087
|
firstDTS = nextAvcDts;
|
@@ -14265,12 +15090,24 @@
|
|
14265
15090
|
inputSamples[0].dts = firstDTS;
|
14266
15091
|
inputSamples[0].pts = firstPTS;
|
14267
15092
|
} else {
|
15093
|
+
var isPTSOrderRetained = true;
|
14268
15094
|
for (var _i = 0; _i < inputSamples.length; _i++) {
|
14269
|
-
if (inputSamples[_i].dts > firstPTS) {
|
15095
|
+
if (inputSamples[_i].dts > firstPTS && isPTSOrderRetained) {
|
14270
15096
|
break;
|
14271
15097
|
}
|
15098
|
+
var prevPTS = inputSamples[_i].pts;
|
14272
15099
|
inputSamples[_i].dts -= delta;
|
14273
15100
|
inputSamples[_i].pts -= delta;
|
15101
|
+
|
15102
|
+
// check to see if this sample's PTS order has changed
|
15103
|
+
// relative to the next one
|
15104
|
+
if (_i < inputSamples.length - 1) {
|
15105
|
+
var nextSamplePTS = inputSamples[_i + 1].pts;
|
15106
|
+
var currentSamplePTS = inputSamples[_i].pts;
|
15107
|
+
var currentOrder = nextSamplePTS <= currentSamplePTS;
|
15108
|
+
var prevOrder = nextSamplePTS <= prevPTS;
|
15109
|
+
isPTSOrderRetained = currentOrder == prevOrder;
|
15110
|
+
}
|
14274
15111
|
}
|
14275
15112
|
}
|
14276
15113
|
logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
|
@@ -14418,7 +15255,7 @@
|
|
14418
15255
|
}
|
14419
15256
|
}
|
14420
15257
|
}
|
14421
|
-
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
15258
|
+
// next AVC/HEVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
14422
15259
|
mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
|
14423
15260
|
this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
|
14424
15261
|
this.videoSampleDuration = mp4SampleDuration;
|
@@ -14553,7 +15390,7 @@
|
|
14553
15390
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
14554
15391
|
for (var j = 0; j < missing; j++) {
|
14555
15392
|
var newStamp = Math.max(nextPts, 0);
|
14556
|
-
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15393
|
+
var fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
|
14557
15394
|
if (!fillFrame) {
|
14558
15395
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
14559
15396
|
fillFrame = sample.unit.subarray();
|
@@ -14681,7 +15518,7 @@
|
|
14681
15518
|
// samples count of this segment's duration
|
14682
15519
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
14683
15520
|
// silent frame
|
14684
|
-
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15521
|
+
var silentFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
|
14685
15522
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
14686
15523
|
// Can't remux if we can't generate a silent frame...
|
14687
15524
|
if (!silentFrame) {
|
@@ -15071,13 +15908,15 @@
|
|
15071
15908
|
duration = transmuxConfig.duration,
|
15072
15909
|
initSegmentData = transmuxConfig.initSegmentData;
|
15073
15910
|
var keyData = getEncryptionType(uintData, decryptdata);
|
15074
|
-
if (keyData && keyData.method
|
15911
|
+
if (keyData && isFullSegmentEncryption(keyData.method)) {
|
15075
15912
|
var decrypter = this.getDecrypter();
|
15913
|
+
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
15914
|
+
|
15076
15915
|
// Software decryption is synchronous; webCrypto is not
|
15077
15916
|
if (decrypter.isSync()) {
|
15078
15917
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
15079
15918
|
// data is handled in the flush() call
|
15080
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
15919
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode);
|
15081
15920
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
15082
15921
|
var loadingParts = chunkMeta.part > -1;
|
15083
15922
|
if (loadingParts) {
|
@@ -15089,7 +15928,7 @@
|
|
15089
15928
|
}
|
15090
15929
|
uintData = new Uint8Array(decryptedData);
|
15091
15930
|
} else {
|
15092
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
15931
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(function (decryptedData) {
|
15093
15932
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
15094
15933
|
// the decrypted data has been transmuxed
|
15095
15934
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -15710,7 +16549,7 @@
|
|
15710
16549
|
observer.on(Events.ERROR, forwardMessage);
|
15711
16550
|
|
15712
16551
|
// forward logger events to main thread
|
15713
|
-
var forwardWorkerLogs = function forwardWorkerLogs() {
|
16552
|
+
var forwardWorkerLogs = function forwardWorkerLogs(logger) {
|
15714
16553
|
var _loop = function _loop(logFn) {
|
15715
16554
|
var func = function func(message) {
|
15716
16555
|
forwardMessage('workerLog', {
|
@@ -15731,8 +16570,8 @@
|
|
15731
16570
|
{
|
15732
16571
|
var config = JSON.parse(data.config);
|
15733
16572
|
self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
|
15734
|
-
enableLogs(config.debug, data.id);
|
15735
|
-
forwardWorkerLogs();
|
16573
|
+
var logger = enableLogs(config.debug, data.id);
|
16574
|
+
forwardWorkerLogs(logger);
|
15736
16575
|
forwardMessage('init', null);
|
15737
16576
|
break;
|
15738
16577
|
}
|
@@ -15906,16 +16745,7 @@
|
|
15906
16745
|
this.observer = new EventEmitter();
|
15907
16746
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
15908
16747
|
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
|
-
};
|
16748
|
+
var m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
|
15919
16749
|
|
15920
16750
|
// navigator.vendor is not always available in Web Worker
|
15921
16751
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -16199,7 +17029,7 @@
|
|
16199
17029
|
_inheritsLoose(AudioStreamController, _BaseStreamController);
|
16200
17030
|
function AudioStreamController(hls, fragmentTracker, keyLoader) {
|
16201
17031
|
var _this;
|
16202
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
17032
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
|
16203
17033
|
_this.videoBuffer = null;
|
16204
17034
|
_this.videoTrackCC = -1;
|
16205
17035
|
_this.waitingVideoCC = -1;
|
@@ -16211,27 +17041,24 @@
|
|
16211
17041
|
_this.flushing = false;
|
16212
17042
|
_this.bufferFlushed = false;
|
16213
17043
|
_this.cachedTrackLoadedData = null;
|
16214
|
-
_this.
|
17044
|
+
_this.registerListeners();
|
16215
17045
|
return _this;
|
16216
17046
|
}
|
16217
17047
|
var _proto = AudioStreamController.prototype;
|
16218
17048
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
16219
|
-
this.
|
17049
|
+
this.unregisterListeners();
|
16220
17050
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
16221
17051
|
this.mainDetails = null;
|
16222
17052
|
this.bufferedTrack = null;
|
16223
17053
|
this.switchingTrack = null;
|
16224
17054
|
};
|
16225
|
-
_proto.
|
17055
|
+
_proto.registerListeners = function registerListeners() {
|
17056
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
16226
17057
|
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
17058
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16231
17059
|
hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16232
17060
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16233
17061
|
hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16234
|
-
hls.on(Events.ERROR, this.onError, this);
|
16235
17062
|
hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
|
16236
17063
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16237
17064
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -16239,16 +17066,16 @@
|
|
16239
17066
|
hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
|
16240
17067
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
16241
17068
|
};
|
16242
|
-
_proto.
|
17069
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
16243
17070
|
var hls = this.hls;
|
16244
|
-
hls
|
16245
|
-
|
16246
|
-
|
17071
|
+
if (!hls) {
|
17072
|
+
return;
|
17073
|
+
}
|
17074
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
16247
17075
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16248
17076
|
hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16249
17077
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16250
17078
|
hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16251
|
-
hls.off(Events.ERROR, this.onError, this);
|
16252
17079
|
hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
|
16253
17080
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16254
17081
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -16407,12 +17234,13 @@
|
|
16407
17234
|
trackId = this.trackId;
|
16408
17235
|
var config = hls.config;
|
16409
17236
|
|
16410
|
-
// 1. if
|
17237
|
+
// 1. if buffering is suspended
|
17238
|
+
// 2. if video not attached AND
|
16411
17239
|
// start fragment already requested OR start frag prefetch not enabled
|
16412
|
-
//
|
17240
|
+
// 3. if tracks or track not loaded and selected
|
16413
17241
|
// then exit loop
|
16414
17242
|
// => 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])) {
|
17243
|
+
if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
16416
17244
|
return;
|
16417
17245
|
}
|
16418
17246
|
var levelInfo = levels[trackId];
|
@@ -16941,7 +17769,7 @@
|
|
16941
17769
|
_inheritsLoose(AudioTrackController, _BasePlaylistControll);
|
16942
17770
|
function AudioTrackController(hls) {
|
16943
17771
|
var _this;
|
16944
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
17772
|
+
_this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
|
16945
17773
|
_this.tracks = [];
|
16946
17774
|
_this.groupIds = null;
|
16947
17775
|
_this.tracksInGroup = [];
|
@@ -17270,26 +18098,23 @@
|
|
17270
18098
|
_inheritsLoose(SubtitleStreamController, _BaseStreamController);
|
17271
18099
|
function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
|
17272
18100
|
var _this;
|
17273
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
18101
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
|
17274
18102
|
_this.currentTrackId = -1;
|
17275
18103
|
_this.tracksBuffered = [];
|
17276
18104
|
_this.mainDetails = null;
|
17277
|
-
_this.
|
18105
|
+
_this.registerListeners();
|
17278
18106
|
return _this;
|
17279
18107
|
}
|
17280
18108
|
var _proto = SubtitleStreamController.prototype;
|
17281
18109
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
17282
|
-
this.
|
18110
|
+
this.unregisterListeners();
|
17283
18111
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
17284
18112
|
this.mainDetails = null;
|
17285
18113
|
};
|
17286
|
-
_proto.
|
18114
|
+
_proto.registerListeners = function registerListeners() {
|
18115
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
17287
18116
|
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
18117
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17292
|
-
hls.on(Events.ERROR, this.onError, this);
|
17293
18118
|
hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17294
18119
|
hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17295
18120
|
hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17297,13 +18122,10 @@
|
|
17297
18122
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
17298
18123
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
17299
18124
|
};
|
17300
|
-
_proto.
|
18125
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
18126
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
17301
18127
|
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
18128
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17306
|
-
hls.off(Events.ERROR, this.onError, this);
|
17307
18129
|
hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17308
18130
|
hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17309
18131
|
hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17526,10 +18348,10 @@
|
|
17526
18348
|
return;
|
17527
18349
|
}
|
17528
18350
|
// check to see if the payload needs to be decrypted
|
17529
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method
|
18351
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
|
17530
18352
|
var startTime = performance.now();
|
17531
18353
|
// decrypt the subtitles
|
17532
|
-
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
18354
|
+
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
|
17533
18355
|
hls.trigger(Events.ERROR, {
|
17534
18356
|
type: ErrorTypes.MEDIA_ERROR,
|
17535
18357
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -17661,7 +18483,7 @@
|
|
17661
18483
|
_inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
|
17662
18484
|
function SubtitleTrackController(hls) {
|
17663
18485
|
var _this;
|
17664
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
18486
|
+
_this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
|
17665
18487
|
_this.media = null;
|
17666
18488
|
_this.tracks = [];
|
17667
18489
|
_this.groupIds = null;
|
@@ -17670,12 +18492,12 @@
|
|
17670
18492
|
_this.currentTrack = null;
|
17671
18493
|
_this.selectDefaultTrack = true;
|
17672
18494
|
_this.queuedDefaultTrack = -1;
|
17673
|
-
_this.asyncPollTrackChange = function () {
|
17674
|
-
return _this.pollTrackChange(0);
|
17675
|
-
};
|
17676
18495
|
_this.useTextTrackPolling = false;
|
17677
18496
|
_this.subtitlePollingInterval = -1;
|
17678
18497
|
_this._subtitleDisplay = true;
|
18498
|
+
_this.asyncPollTrackChange = function () {
|
18499
|
+
return _this.pollTrackChange(0);
|
18500
|
+
};
|
17679
18501
|
_this.onTextTracksChanged = function () {
|
17680
18502
|
if (!_this.useTextTrackPolling) {
|
17681
18503
|
self.clearInterval(_this.subtitlePollingInterval);
|
@@ -17711,6 +18533,7 @@
|
|
17711
18533
|
this.tracks.length = 0;
|
17712
18534
|
this.tracksInGroup.length = 0;
|
17713
18535
|
this.currentTrack = null;
|
18536
|
+
// @ts-ignore
|
17714
18537
|
this.onTextTracksChanged = this.asyncPollTrackChange = null;
|
17715
18538
|
_BasePlaylistControll.prototype.destroy.call(this);
|
17716
18539
|
};
|
@@ -18184,57 +19007,57 @@
|
|
18184
19007
|
}();
|
18185
19008
|
|
18186
19009
|
var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
|
18187
|
-
var BufferController = /*#__PURE__*/function () {
|
19010
|
+
var BufferController = /*#__PURE__*/function (_Logger) {
|
19011
|
+
_inheritsLoose(BufferController, _Logger);
|
18188
19012
|
function BufferController(hls) {
|
18189
|
-
var _this
|
19013
|
+
var _this;
|
19014
|
+
_this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
|
18190
19015
|
// The level details used to determine duration, target-duration and live
|
18191
|
-
|
19016
|
+
_this.details = null;
|
18192
19017
|
// cache the self generated object url to detect hijack of video tag
|
18193
|
-
|
19018
|
+
_this._objectUrl = null;
|
18194
19019
|
// A queue of buffer operations which require the SourceBuffer to not be updating upon execution
|
18195
|
-
|
19020
|
+
_this.operationQueue = void 0;
|
18196
19021
|
// References to event listeners for each SourceBuffer, so that they can be referenced for event removal
|
18197
|
-
|
18198
|
-
|
19022
|
+
_this.listeners = void 0;
|
19023
|
+
_this.hls = void 0;
|
18199
19024
|
// The number of BUFFER_CODEC events received before any sourceBuffers are created
|
18200
|
-
|
19025
|
+
_this.bufferCodecEventsExpected = 0;
|
18201
19026
|
// The total number of BUFFER_CODEC events received
|
18202
|
-
|
19027
|
+
_this._bufferCodecEventsTotal = 0;
|
18203
19028
|
// A reference to the attached media element
|
18204
|
-
|
19029
|
+
_this.media = null;
|
18205
19030
|
// A reference to the active media source
|
18206
|
-
|
19031
|
+
_this.mediaSource = null;
|
18207
19032
|
// Last MP3 audio chunk appended
|
18208
|
-
|
18209
|
-
|
19033
|
+
_this.lastMpegAudioChunk = null;
|
19034
|
+
_this.appendSource = void 0;
|
18210
19035
|
// counters
|
18211
|
-
|
19036
|
+
_this.appendErrors = {
|
18212
19037
|
audio: 0,
|
18213
19038
|
video: 0,
|
18214
19039
|
audiovideo: 0
|
18215
19040
|
};
|
18216
|
-
|
18217
|
-
|
18218
|
-
|
18219
|
-
|
18220
|
-
this.warn = void 0;
|
18221
|
-
this.error = void 0;
|
18222
|
-
this._onEndStreaming = function (event) {
|
19041
|
+
_this.tracks = {};
|
19042
|
+
_this.pendingTracks = {};
|
19043
|
+
_this.sourceBuffer = void 0;
|
19044
|
+
_this._onEndStreaming = function (event) {
|
18223
19045
|
if (!_this.hls) {
|
18224
19046
|
return;
|
18225
19047
|
}
|
18226
19048
|
_this.hls.pauseBuffering();
|
18227
19049
|
};
|
18228
|
-
|
19050
|
+
_this._onStartStreaming = function (event) {
|
18229
19051
|
if (!_this.hls) {
|
18230
19052
|
return;
|
18231
19053
|
}
|
18232
19054
|
_this.hls.resumeBuffering();
|
18233
19055
|
};
|
18234
19056
|
// Keep as arrow functions so that we can directly reference these functions directly as event listeners
|
18235
|
-
|
18236
|
-
var
|
18237
|
-
|
19057
|
+
_this._onMediaSourceOpen = function () {
|
19058
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
19059
|
+
media = _assertThisInitialize.media,
|
19060
|
+
mediaSource = _assertThisInitialize.mediaSource;
|
18238
19061
|
_this.log('Media source opened');
|
18239
19062
|
if (media) {
|
18240
19063
|
media.removeEventListener('emptied', _this._onMediaEmptied);
|
@@ -18250,27 +19073,25 @@
|
|
18250
19073
|
}
|
18251
19074
|
_this.checkPendingTracks();
|
18252
19075
|
};
|
18253
|
-
|
19076
|
+
_this._onMediaSourceClose = function () {
|
18254
19077
|
_this.log('Media source closed');
|
18255
19078
|
};
|
18256
|
-
|
19079
|
+
_this._onMediaSourceEnded = function () {
|
18257
19080
|
_this.log('Media source ended');
|
18258
19081
|
};
|
18259
|
-
|
18260
|
-
var
|
18261
|
-
|
19082
|
+
_this._onMediaEmptied = function () {
|
19083
|
+
var _assertThisInitialize2 = _assertThisInitialized(_this),
|
19084
|
+
mediaSrc = _assertThisInitialize2.mediaSrc,
|
19085
|
+
_objectUrl = _assertThisInitialize2._objectUrl;
|
18262
19086
|
if (mediaSrc !== _objectUrl) {
|
18263
|
-
|
19087
|
+
_this.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
|
18264
19088
|
}
|
18265
19089
|
};
|
18266
|
-
|
18267
|
-
|
18268
|
-
|
18269
|
-
|
18270
|
-
|
18271
|
-
this.error = logger.error.bind(logger, logPrefix);
|
18272
|
-
this._initSourceBuffer();
|
18273
|
-
this.registerListeners();
|
19090
|
+
_this.hls = hls;
|
19091
|
+
_this.appendSource = hls.config.preferManagedMediaSource;
|
19092
|
+
_this._initSourceBuffer();
|
19093
|
+
_this.registerListeners();
|
19094
|
+
return _this;
|
18274
19095
|
}
|
18275
19096
|
var _proto = BufferController.prototype;
|
18276
19097
|
_proto.hasSourceTypes = function hasSourceTypes() {
|
@@ -18282,6 +19103,12 @@
|
|
18282
19103
|
this.lastMpegAudioChunk = null;
|
18283
19104
|
// @ts-ignore
|
18284
19105
|
this.hls = null;
|
19106
|
+
// @ts-ignore
|
19107
|
+
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
19108
|
+
// @ts-ignore
|
19109
|
+
this._onMediaSourceEnded = null;
|
19110
|
+
// @ts-ignore
|
19111
|
+
this._onStartStreaming = this._onEndStreaming = null;
|
18285
19112
|
};
|
18286
19113
|
_proto.registerListeners = function registerListeners() {
|
18287
19114
|
var hls = this.hls;
|
@@ -18439,6 +19266,7 @@
|
|
18439
19266
|
_this2.resetBuffer(type);
|
18440
19267
|
});
|
18441
19268
|
this._initSourceBuffer();
|
19269
|
+
this.hls.resumeBuffering();
|
18442
19270
|
};
|
18443
19271
|
_proto.resetBuffer = function resetBuffer(type) {
|
18444
19272
|
var sb = this.sourceBuffer[type];
|
@@ -19142,7 +19970,7 @@
|
|
19142
19970
|
}
|
19143
19971
|
}]);
|
19144
19972
|
return BufferController;
|
19145
|
-
}();
|
19973
|
+
}(Logger);
|
19146
19974
|
function removeSourceChildren(node) {
|
19147
19975
|
var sourceChildren = node.querySelectorAll('source');
|
19148
19976
|
[].slice.call(sourceChildren).forEach(function (source) {
|
@@ -21581,14 +22409,12 @@
|
|
21581
22409
|
this.cea608Parser1 = this.cea608Parser2 = undefined;
|
21582
22410
|
};
|
21583
22411
|
_proto.initCea608Parsers = function initCea608Parsers() {
|
21584
|
-
|
21585
|
-
|
21586
|
-
|
21587
|
-
|
21588
|
-
|
21589
|
-
|
21590
|
-
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21591
|
-
}
|
22412
|
+
var channel1 = new OutputFilter(this, 'textTrack1');
|
22413
|
+
var channel2 = new OutputFilter(this, 'textTrack2');
|
22414
|
+
var channel3 = new OutputFilter(this, 'textTrack3');
|
22415
|
+
var channel4 = new OutputFilter(this, 'textTrack4');
|
22416
|
+
this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
|
22417
|
+
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21592
22418
|
};
|
21593
22419
|
_proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
|
21594
22420
|
// skip cues which overlap more than 50% with previously parsed time ranges
|
@@ -21823,7 +22649,7 @@
|
|
21823
22649
|
return t.label;
|
21824
22650
|
});
|
21825
22651
|
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.");
|
22652
|
+
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
22653
|
}
|
21828
22654
|
}
|
21829
22655
|
} else if (this.tracks.length) {
|
@@ -21869,23 +22695,20 @@
|
|
21869
22695
|
return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
|
21870
22696
|
};
|
21871
22697
|
_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
22698
|
// 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) {
|
22699
|
+
if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
|
21883
22700
|
var _data$part$index, _data$part;
|
22701
|
+
var cea608Parser1 = this.cea608Parser1,
|
22702
|
+
cea608Parser2 = this.cea608Parser2,
|
22703
|
+
lastSn = this.lastSn;
|
22704
|
+
if (!cea608Parser1 || !cea608Parser2) {
|
22705
|
+
return;
|
22706
|
+
}
|
21884
22707
|
var _data$frag = data.frag,
|
21885
22708
|
cc = _data$frag.cc,
|
21886
22709
|
sn = _data$frag.sn;
|
21887
|
-
var partIndex = (_data$part$index =
|
21888
|
-
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
|
22710
|
+
var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
22711
|
+
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === this.lastPartIndex + 1 || cc === this.lastCc)) {
|
21889
22712
|
cea608Parser1.reset();
|
21890
22713
|
cea608Parser2.reset();
|
21891
22714
|
}
|
@@ -21941,7 +22764,7 @@
|
|
21941
22764
|
frag: frag
|
21942
22765
|
});
|
21943
22766
|
}, function (error) {
|
21944
|
-
logger.log("Failed to parse IMSC1: " + error);
|
22767
|
+
hls.logger.log("Failed to parse IMSC1: " + error);
|
21945
22768
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
21946
22769
|
success: false,
|
21947
22770
|
frag: frag,
|
@@ -21979,7 +22802,7 @@
|
|
21979
22802
|
_this5._fallbackToIMSC1(frag, payload);
|
21980
22803
|
}
|
21981
22804
|
// Something went wrong while parsing. Trigger event with success false.
|
21982
|
-
logger.log("Failed to parse VTT cue: " + error);
|
22805
|
+
hls.logger.log("Failed to parse VTT cue: " + error);
|
21983
22806
|
if (missingInitPTS && maxAvCC > frag.cc) {
|
21984
22807
|
return;
|
21985
22808
|
}
|
@@ -22041,10 +22864,7 @@
|
|
22041
22864
|
this.captionsTracks = {};
|
22042
22865
|
};
|
22043
22866
|
_proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
|
22044
|
-
this.
|
22045
|
-
var cea608Parser1 = this.cea608Parser1,
|
22046
|
-
cea608Parser2 = this.cea608Parser2;
|
22047
|
-
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
22867
|
+
if (!this.enabled || !this.config.enableCEA708Captions) {
|
22048
22868
|
return;
|
22049
22869
|
}
|
22050
22870
|
var frag = data.frag,
|
@@ -22057,9 +22877,12 @@
|
|
22057
22877
|
for (var i = 0; i < samples.length; i++) {
|
22058
22878
|
var ccBytes = samples[i].bytes;
|
22059
22879
|
if (ccBytes) {
|
22880
|
+
if (!this.cea608Parser1) {
|
22881
|
+
this.initCea608Parsers();
|
22882
|
+
}
|
22060
22883
|
var ccdatas = this.extractCea608Data(ccBytes);
|
22061
|
-
cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22062
|
-
cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22884
|
+
this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22885
|
+
this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22063
22886
|
}
|
22064
22887
|
}
|
22065
22888
|
};
|
@@ -22251,7 +23074,7 @@
|
|
22251
23074
|
var hls = this.hls;
|
22252
23075
|
var maxLevel = this.getMaxLevel(levels.length - 1);
|
22253
23076
|
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);
|
23077
|
+
hls.logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
22255
23078
|
}
|
22256
23079
|
hls.autoLevelCapping = maxLevel;
|
22257
23080
|
if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
|
@@ -22441,10 +23264,10 @@
|
|
22441
23264
|
totalDroppedFrames: droppedFrames
|
22442
23265
|
});
|
22443
23266
|
if (droppedFPS > 0) {
|
22444
|
-
// logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
23267
|
+
// hls.logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
22445
23268
|
if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
|
22446
23269
|
var currentLevel = hls.currentLevel;
|
22447
|
-
logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
23270
|
+
hls.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
22448
23271
|
if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
|
22449
23272
|
currentLevel = currentLevel - 1;
|
22450
23273
|
hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
|
@@ -22477,7 +23300,6 @@
|
|
22477
23300
|
return FPSController;
|
22478
23301
|
}();
|
22479
23302
|
|
22480
|
-
var LOGGER_PREFIX = '[eme]';
|
22481
23303
|
/**
|
22482
23304
|
* Controller to deal with encrypted media extensions (EME)
|
22483
23305
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
|
@@ -22485,26 +23307,122 @@
|
|
22485
23307
|
* @class
|
22486
23308
|
* @constructor
|
22487
23309
|
*/
|
22488
|
-
var EMEController = /*#__PURE__*/function () {
|
23310
|
+
var EMEController = /*#__PURE__*/function (_Logger) {
|
23311
|
+
_inheritsLoose(EMEController, _Logger);
|
22489
23312
|
function EMEController(hls) {
|
22490
|
-
|
22491
|
-
this.
|
22492
|
-
|
22493
|
-
|
22494
|
-
|
22495
|
-
|
22496
|
-
|
22497
|
-
|
22498
|
-
|
22499
|
-
|
22500
|
-
|
22501
|
-
|
22502
|
-
|
22503
|
-
|
22504
|
-
|
22505
|
-
|
22506
|
-
|
22507
|
-
|
23313
|
+
var _this;
|
23314
|
+
_this = _Logger.call(this, 'eme', hls.logger) || this;
|
23315
|
+
_this.hls = void 0;
|
23316
|
+
_this.config = void 0;
|
23317
|
+
_this.media = null;
|
23318
|
+
_this.keyFormatPromise = null;
|
23319
|
+
_this.keySystemAccessPromises = {};
|
23320
|
+
_this._requestLicenseFailureCount = 0;
|
23321
|
+
_this.mediaKeySessions = [];
|
23322
|
+
_this.keyIdToKeySessionPromise = {};
|
23323
|
+
_this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
23324
|
+
_this.onMediaEncrypted = function (event) {
|
23325
|
+
var initDataType = event.initDataType,
|
23326
|
+
initData = event.initData;
|
23327
|
+
_this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
23328
|
+
|
23329
|
+
// Ignore event when initData is null
|
23330
|
+
if (initData === null) {
|
23331
|
+
return;
|
23332
|
+
}
|
23333
|
+
var keyId;
|
23334
|
+
var keySystemDomain;
|
23335
|
+
if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
23336
|
+
// Match sinf keyId to playlist skd://keyId=
|
23337
|
+
var json = bin2str(new Uint8Array(initData));
|
23338
|
+
try {
|
23339
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
23340
|
+
var tenc = parseSinf(new Uint8Array(sinf));
|
23341
|
+
if (!tenc) {
|
23342
|
+
return;
|
23343
|
+
}
|
23344
|
+
keyId = tenc.subarray(8, 24);
|
23345
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
23346
|
+
} catch (error) {
|
23347
|
+
_this.warn('Failed to parse sinf "encrypted" event message initData');
|
23348
|
+
return;
|
23349
|
+
}
|
23350
|
+
} else {
|
23351
|
+
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
23352
|
+
var psshInfo = parsePssh(initData);
|
23353
|
+
if (psshInfo === null) {
|
23354
|
+
return;
|
23355
|
+
}
|
23356
|
+
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
23357
|
+
keyId = psshInfo.data.subarray(8, 24);
|
23358
|
+
}
|
23359
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
23360
|
+
}
|
23361
|
+
if (!keySystemDomain || !keyId) {
|
23362
|
+
return;
|
23363
|
+
}
|
23364
|
+
var keyIdHex = Hex.hexDump(keyId);
|
23365
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
23366
|
+
keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
|
23367
|
+
mediaKeySessions = _assertThisInitialize.mediaKeySessions;
|
23368
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
23369
|
+
var _loop = function _loop() {
|
23370
|
+
// Match playlist key
|
23371
|
+
var keyContext = mediaKeySessions[i];
|
23372
|
+
var decryptdata = keyContext.decryptdata;
|
23373
|
+
if (decryptdata.pssh || !decryptdata.keyId) {
|
23374
|
+
return 0; // continue
|
23375
|
+
}
|
23376
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
23377
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
23378
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
23379
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
23380
|
+
decryptdata.pssh = new Uint8Array(initData);
|
23381
|
+
decryptdata.keyId = keyId;
|
23382
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
23383
|
+
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
23384
|
+
});
|
23385
|
+
return 1; // break
|
23386
|
+
}
|
23387
|
+
},
|
23388
|
+
_ret;
|
23389
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
23390
|
+
_ret = _loop();
|
23391
|
+
if (_ret === 0) continue;
|
23392
|
+
if (_ret === 1) break;
|
23393
|
+
}
|
23394
|
+
if (!keySessionContextPromise) {
|
23395
|
+
// Clear-lead key (not encountered in playlist)
|
23396
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
23397
|
+
var _keySystemToKeySystem;
|
23398
|
+
var keySystem = _ref.keySystem,
|
23399
|
+
mediaKeys = _ref.mediaKeys;
|
23400
|
+
_this.throwIfDestroyed();
|
23401
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
23402
|
+
decryptdata.pssh = new Uint8Array(initData);
|
23403
|
+
decryptdata.keyId = keyId;
|
23404
|
+
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23405
|
+
_this.throwIfDestroyed();
|
23406
|
+
var keySessionContext = _this.createMediaKeySessionContext({
|
23407
|
+
decryptdata: decryptdata,
|
23408
|
+
keySystem: keySystem,
|
23409
|
+
mediaKeys: mediaKeys
|
23410
|
+
});
|
23411
|
+
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
23412
|
+
});
|
23413
|
+
});
|
23414
|
+
}
|
23415
|
+
keySessionContextPromise.catch(function (error) {
|
23416
|
+
return _this.handleError(error);
|
23417
|
+
});
|
23418
|
+
};
|
23419
|
+
_this.onWaitingForKey = function (event) {
|
23420
|
+
_this.log("\"" + event.type + "\" event");
|
23421
|
+
};
|
23422
|
+
_this.hls = hls;
|
23423
|
+
_this.config = hls.config;
|
23424
|
+
_this.registerListeners();
|
23425
|
+
return _this;
|
22508
23426
|
}
|
22509
23427
|
var _proto = EMEController.prototype;
|
22510
23428
|
_proto.destroy = function destroy() {
|
@@ -22516,9 +23434,9 @@
|
|
22516
23434
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
22517
23435
|
config.drmSystems = config.drmSystemOptions = {};
|
22518
23436
|
// @ts-ignore
|
22519
|
-
this.hls = this.
|
23437
|
+
this.hls = this.config = this.keyIdToKeySessionPromise = null;
|
22520
23438
|
// @ts-ignore
|
22521
|
-
this.
|
23439
|
+
this.onMediaEncrypted = this.onWaitingForKey = null;
|
22522
23440
|
};
|
22523
23441
|
_proto.registerListeners = function registerListeners() {
|
22524
23442
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -22557,7 +23475,7 @@
|
|
22557
23475
|
}
|
22558
23476
|
};
|
22559
23477
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
22560
|
-
var
|
23478
|
+
var _this2 = this;
|
22561
23479
|
var levels = this.hls.levels;
|
22562
23480
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
22563
23481
|
return !!value && a.indexOf(value) === i;
|
@@ -22574,7 +23492,7 @@
|
|
22574
23492
|
return new Promise(function (resolve, reject) {
|
22575
23493
|
var attempt = function attempt(keySystems) {
|
22576
23494
|
var keySystem = keySystems.shift();
|
22577
|
-
|
23495
|
+
_this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
22578
23496
|
return resolve({
|
22579
23497
|
keySystem: keySystem,
|
22580
23498
|
mediaKeys: mediaKeys
|
@@ -22609,7 +23527,7 @@
|
|
22609
23527
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
22610
23528
|
};
|
22611
23529
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
22612
|
-
var
|
23530
|
+
var _this3 = this;
|
22613
23531
|
// This can throw, but is caught in event handler callpath
|
22614
23532
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
22615
23533
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -22621,23 +23539,23 @@
|
|
22621
23539
|
keySystemAccess: keySystemAccess
|
22622
23540
|
};
|
22623
23541
|
keySystemAccess.catch(function (error) {
|
22624
|
-
|
23542
|
+
_this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
22625
23543
|
});
|
22626
23544
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
22627
|
-
|
22628
|
-
var certificateRequest =
|
22629
|
-
|
23545
|
+
_this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
23546
|
+
var certificateRequest = _this3.fetchServerCertificate(keySystem);
|
23547
|
+
_this3.log("Create media-keys for \"" + keySystem + "\"");
|
22630
23548
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
22631
|
-
|
23549
|
+
_this3.log("Media-keys created for \"" + keySystem + "\"");
|
22632
23550
|
return certificateRequest.then(function (certificate) {
|
22633
23551
|
if (certificate) {
|
22634
|
-
return
|
23552
|
+
return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
22635
23553
|
}
|
22636
23554
|
return mediaKeys;
|
22637
23555
|
});
|
22638
23556
|
});
|
22639
23557
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
22640
|
-
|
23558
|
+
_this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
22641
23559
|
});
|
22642
23560
|
return _keySystemAccessPromises.mediaKeys;
|
22643
23561
|
});
|
@@ -22646,10 +23564,10 @@
|
|
22646
23564
|
return keySystemAccessPromises.mediaKeys;
|
22647
23565
|
});
|
22648
23566
|
};
|
22649
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
22650
|
-
var decryptdata =
|
22651
|
-
keySystem =
|
22652
|
-
mediaKeys =
|
23567
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
|
23568
|
+
var decryptdata = _ref2.decryptdata,
|
23569
|
+
keySystem = _ref2.keySystem,
|
23570
|
+
mediaKeys = _ref2.mediaKeys;
|
22653
23571
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
22654
23572
|
var mediaKeysSession = mediaKeys.createSession();
|
22655
23573
|
var mediaKeySessionContext = {
|
@@ -22698,14 +23616,14 @@
|
|
22698
23616
|
return this.keyFormatPromise;
|
22699
23617
|
};
|
22700
23618
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
22701
|
-
var
|
23619
|
+
var _this4 = this;
|
22702
23620
|
return new Promise(function (resolve, reject) {
|
22703
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
23621
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
|
22704
23622
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
22705
23623
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
22706
23624
|
});
|
22707
|
-
return
|
22708
|
-
var keySystem =
|
23625
|
+
return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
|
23626
|
+
var keySystem = _ref3.keySystem;
|
22709
23627
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
22710
23628
|
if (keySystemFormat) {
|
22711
23629
|
resolve(keySystemFormat);
|
@@ -22716,31 +23634,31 @@
|
|
22716
23634
|
});
|
22717
23635
|
};
|
22718
23636
|
_proto.loadKey = function loadKey(data) {
|
22719
|
-
var
|
23637
|
+
var _this5 = this;
|
22720
23638
|
var decryptdata = data.keyInfo.decryptdata;
|
22721
23639
|
var keyId = this.getKeyIdString(decryptdata);
|
22722
23640
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
22723
23641
|
this.log("Starting session for key " + keyDetails);
|
22724
23642
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
22725
23643
|
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 =
|
23644
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
|
23645
|
+
var keySystem = _ref4.keySystem,
|
23646
|
+
mediaKeys = _ref4.mediaKeys;
|
23647
|
+
_this5.throwIfDestroyed();
|
23648
|
+
_this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
23649
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23650
|
+
_this5.throwIfDestroyed();
|
23651
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22734
23652
|
keySystem: keySystem,
|
22735
23653
|
mediaKeys: mediaKeys,
|
22736
23654
|
decryptdata: decryptdata
|
22737
23655
|
});
|
22738
23656
|
var scheme = 'cenc';
|
22739
|
-
return
|
23657
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
22740
23658
|
});
|
22741
23659
|
});
|
22742
23660
|
keySessionContextPromise.catch(function (error) {
|
22743
|
-
return
|
23661
|
+
return _this5.handleError(error);
|
22744
23662
|
});
|
22745
23663
|
}
|
22746
23664
|
return keySessionContextPromise;
|
@@ -22766,128 +23684,30 @@
|
|
22766
23684
|
});
|
22767
23685
|
}
|
22768
23686
|
};
|
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
|
-
});
|
23687
|
+
_proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
|
23688
|
+
var keyId = this.getKeyIdString(decryptdata);
|
23689
|
+
var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
|
23690
|
+
if (!mediaKeySessionContext) {
|
23691
|
+
var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
|
23692
|
+
var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
|
23693
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22884
23694
|
}
|
22885
|
-
|
22886
|
-
return _this5.handleError(error);
|
22887
|
-
});
|
23695
|
+
return mediaKeySessionContext;
|
22888
23696
|
};
|
22889
|
-
_proto.
|
22890
|
-
|
23697
|
+
_proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
|
23698
|
+
if (!keySystemsToAttempt.length) {
|
23699
|
+
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
23700
|
+
}
|
23701
|
+
if (keySystemsToAttempt.length === 0) {
|
23702
|
+
throw new EMEKeyError({
|
23703
|
+
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
23704
|
+
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
23705
|
+
fatal: true
|
23706
|
+
}, "Missing key-system license configuration options " + JSON.stringify({
|
23707
|
+
drmSystems: this.config.drmSystems
|
23708
|
+
}));
|
23709
|
+
}
|
23710
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22891
23711
|
};
|
22892
23712
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
22893
23713
|
var _this6 = this;
|
@@ -23344,7 +24164,7 @@
|
|
23344
24164
|
}
|
23345
24165
|
};
|
23346
24166
|
return EMEController;
|
23347
|
-
}();
|
24167
|
+
}(Logger);
|
23348
24168
|
EMEController.CDMCleanupPromise = void 0;
|
23349
24169
|
var EMEKeyError = /*#__PURE__*/function (_Error) {
|
23350
24170
|
_inheritsLoose(EMEKeyError, _Error);
|
@@ -23492,18 +24312,6 @@
|
|
23492
24312
|
this.params = params;
|
23493
24313
|
};
|
23494
24314
|
|
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
24315
|
var DICT = 'Dict';
|
23508
24316
|
|
23509
24317
|
function format(value) {
|
@@ -23527,29 +24335,25 @@
|
|
23527
24335
|
});
|
23528
24336
|
}
|
23529
24337
|
|
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;
|
24338
|
+
function serializeError(src, type, cause) {
|
24339
|
+
return throwError('serialize', src, type, cause);
|
23542
24340
|
}
|
23543
24341
|
|
23544
|
-
|
23545
|
-
|
23546
|
-
|
24342
|
+
/**
|
24343
|
+
* A class to represent structured field tokens when `Symbol` is not available.
|
24344
|
+
*
|
24345
|
+
* @group Structured Field
|
24346
|
+
*
|
24347
|
+
* @beta
|
24348
|
+
*/
|
24349
|
+
var SfToken = function SfToken(description) {
|
24350
|
+
this.description = void 0;
|
24351
|
+
this.description = description;
|
24352
|
+
};
|
23547
24353
|
|
23548
|
-
var
|
24354
|
+
var BARE_ITEM = 'Bare Item';
|
23549
24355
|
|
23550
|
-
|
23551
|
-
return throwError('serialize', src, type, cause);
|
23552
|
-
}
|
24356
|
+
var BOOLEAN = 'Boolean';
|
23553
24357
|
|
23554
24358
|
// 4.1.9. Serializing a Boolean
|
23555
24359
|
//
|
@@ -23588,6 +24392,8 @@
|
|
23588
24392
|
return btoa(String.fromCharCode.apply(String, binary));
|
23589
24393
|
}
|
23590
24394
|
|
24395
|
+
var BYTES = 'Byte Sequence';
|
24396
|
+
|
23591
24397
|
// 4.1.8. Serializing a Byte Sequence
|
23592
24398
|
//
|
23593
24399
|
// Given a Byte Sequence as input_bytes, return an ASCII string suitable
|
@@ -23619,6 +24425,12 @@
|
|
23619
24425
|
return ":" + base64encode(value) + ":";
|
23620
24426
|
}
|
23621
24427
|
|
24428
|
+
var INTEGER = 'Integer';
|
24429
|
+
|
24430
|
+
function isInvalidInt(value) {
|
24431
|
+
return value < -999999999999999 || 999999999999999 < value;
|
24432
|
+
}
|
24433
|
+
|
23622
24434
|
// 4.1.4. Serializing an Integer
|
23623
24435
|
//
|
23624
24436
|
// Given an Integer as input_integer, return an ASCII string suitable
|
@@ -23684,6 +24496,8 @@
|
|
23684
24496
|
}
|
23685
24497
|
}
|
23686
24498
|
|
24499
|
+
var DECIMAL = 'Decimal';
|
24500
|
+
|
23687
24501
|
// 4.1.5. Serializing a Decimal
|
23688
24502
|
//
|
23689
24503
|
// Given a decimal number as input_decimal, return an ASCII string
|
@@ -23729,6 +24543,8 @@
|
|
23729
24543
|
|
23730
24544
|
var STRING = 'String';
|
23731
24545
|
|
24546
|
+
var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
|
24547
|
+
|
23732
24548
|
// 4.1.6. Serializing a String
|
23733
24549
|
//
|
23734
24550
|
// Given a String as input_string, return an ASCII string suitable for
|
@@ -23764,6 +24580,8 @@
|
|
23764
24580
|
return symbol.description || symbol.toString().slice(7, -1);
|
23765
24581
|
}
|
23766
24582
|
|
24583
|
+
var TOKEN = 'Token';
|
24584
|
+
|
23767
24585
|
function serializeToken(token) {
|
23768
24586
|
var value = symbolToStr(token);
|
23769
24587
|
if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
|
@@ -23831,6 +24649,8 @@
|
|
23831
24649
|
}
|
23832
24650
|
}
|
23833
24651
|
|
24652
|
+
var KEY = 'Key';
|
24653
|
+
|
23834
24654
|
// 4.1.1.3. Serializing a Key
|
23835
24655
|
//
|
23836
24656
|
// Given a key as input_key, return an ASCII string suitable for use in
|
@@ -24082,36 +24902,6 @@
|
|
24082
24902
|
return toPath.join('/');
|
24083
24903
|
}
|
24084
24904
|
|
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
24905
|
var toRounded = function toRounded(value) {
|
24116
24906
|
return Math.round(value);
|
24117
24907
|
};
|
@@ -24356,6 +25146,36 @@
|
|
24356
25146
|
return "" + url + separator + query;
|
24357
25147
|
}
|
24358
25148
|
|
25149
|
+
/**
|
25150
|
+
* Generate a random v4 UUID
|
25151
|
+
*
|
25152
|
+
* @returns A random v4 UUID
|
25153
|
+
*
|
25154
|
+
* @group Utils
|
25155
|
+
*
|
25156
|
+
* @beta
|
25157
|
+
*/
|
25158
|
+
function uuid() {
|
25159
|
+
try {
|
25160
|
+
return crypto.randomUUID();
|
25161
|
+
} catch (error) {
|
25162
|
+
try {
|
25163
|
+
var url = URL.createObjectURL(new Blob());
|
25164
|
+
var _uuid = url.toString();
|
25165
|
+
URL.revokeObjectURL(url);
|
25166
|
+
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
25167
|
+
} catch (error) {
|
25168
|
+
var dt = new Date().getTime();
|
25169
|
+
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
25170
|
+
var r = (dt + Math.random() * 16) % 16 | 0;
|
25171
|
+
dt = Math.floor(dt / 16);
|
25172
|
+
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
25173
|
+
});
|
25174
|
+
return _uuid2;
|
25175
|
+
}
|
25176
|
+
}
|
25177
|
+
}
|
25178
|
+
|
24359
25179
|
/**
|
24360
25180
|
* Controller to deal with Common Media Client Data (CMCD)
|
24361
25181
|
* @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
|
@@ -24420,6 +25240,12 @@
|
|
24420
25240
|
data.tb = _this.getTopBandwidth(ot) / 1000;
|
24421
25241
|
data.bl = _this.getBufferLength(ot);
|
24422
25242
|
}
|
25243
|
+
var next = _this.getNextFrag(fragment);
|
25244
|
+
if (next) {
|
25245
|
+
if (next.url && next.url !== fragment.url) {
|
25246
|
+
data.nor = next.url;
|
25247
|
+
}
|
25248
|
+
}
|
24423
25249
|
_this.apply(context, data);
|
24424
25250
|
} catch (error) {
|
24425
25251
|
logger.warn('Could not generate segment CMCD data.', error);
|
@@ -24514,7 +25340,7 @@
|
|
24514
25340
|
data.su = this.buffering;
|
24515
25341
|
}
|
24516
25342
|
|
24517
|
-
// TODO: Implement rtp, nrr,
|
25343
|
+
// TODO: Implement rtp, nrr, dl
|
24518
25344
|
|
24519
25345
|
var includeKeys = this.includeKeys;
|
24520
25346
|
if (includeKeys) {
|
@@ -24523,18 +25349,31 @@
|
|
24523
25349
|
return acc;
|
24524
25350
|
}, {});
|
24525
25351
|
}
|
25352
|
+
var options = {
|
25353
|
+
baseUrl: context.url
|
25354
|
+
};
|
24526
25355
|
if (this.useHeaders) {
|
24527
25356
|
if (!context.headers) {
|
24528
25357
|
context.headers = {};
|
24529
25358
|
}
|
24530
|
-
appendCmcdHeaders(context.headers, data);
|
25359
|
+
appendCmcdHeaders(context.headers, data, options);
|
24531
25360
|
} else {
|
24532
|
-
context.url = appendCmcdQuery(context.url, data);
|
25361
|
+
context.url = appendCmcdQuery(context.url, data, options);
|
24533
25362
|
}
|
24534
25363
|
};
|
25364
|
+
_proto.getNextFrag = function getNextFrag(fragment) {
|
25365
|
+
var _this$hls$levels$frag;
|
25366
|
+
var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
|
25367
|
+
if (levelDetails) {
|
25368
|
+
var index = fragment.sn - levelDetails.startSN;
|
25369
|
+
return levelDetails.fragments[index + 1];
|
25370
|
+
}
|
25371
|
+
return undefined;
|
25372
|
+
}
|
25373
|
+
|
24535
25374
|
/**
|
24536
25375
|
* The CMCD object type.
|
24537
|
-
|
25376
|
+
*/;
|
24538
25377
|
_proto.getObjectType = function getObjectType(fragment) {
|
24539
25378
|
var type = fragment.type;
|
24540
25379
|
if (type === 'subtitle') {
|
@@ -24670,26 +25509,28 @@
|
|
24670
25509
|
}();
|
24671
25510
|
|
24672
25511
|
var PATHWAY_PENALTY_DURATION_MS = 300000;
|
24673
|
-
var ContentSteeringController = /*#__PURE__*/function () {
|
25512
|
+
var ContentSteeringController = /*#__PURE__*/function (_Logger) {
|
25513
|
+
_inheritsLoose(ContentSteeringController, _Logger);
|
24674
25514
|
function ContentSteeringController(hls) {
|
24675
|
-
|
24676
|
-
this.
|
24677
|
-
|
24678
|
-
|
24679
|
-
|
24680
|
-
|
24681
|
-
|
24682
|
-
|
24683
|
-
|
24684
|
-
|
24685
|
-
|
24686
|
-
|
24687
|
-
|
24688
|
-
|
24689
|
-
|
24690
|
-
|
24691
|
-
|
24692
|
-
|
25515
|
+
var _this;
|
25516
|
+
_this = _Logger.call(this, 'content-steering', hls.logger) || this;
|
25517
|
+
_this.hls = void 0;
|
25518
|
+
_this.loader = null;
|
25519
|
+
_this.uri = null;
|
25520
|
+
_this.pathwayId = '.';
|
25521
|
+
_this.pathwayPriority = null;
|
25522
|
+
_this.timeToLoad = 300;
|
25523
|
+
_this.reloadTimer = -1;
|
25524
|
+
_this.updated = 0;
|
25525
|
+
_this.started = false;
|
25526
|
+
_this.enabled = true;
|
25527
|
+
_this.levels = null;
|
25528
|
+
_this.audioTracks = null;
|
25529
|
+
_this.subtitleTracks = null;
|
25530
|
+
_this.penalizedPathways = {};
|
25531
|
+
_this.hls = hls;
|
25532
|
+
_this.registerListeners();
|
25533
|
+
return _this;
|
24693
25534
|
}
|
24694
25535
|
var _proto = ContentSteeringController.prototype;
|
24695
25536
|
_proto.registerListeners = function registerListeners() {
|
@@ -24810,7 +25651,7 @@
|
|
24810
25651
|
errorAction.resolved = this.pathwayId !== errorPathway;
|
24811
25652
|
}
|
24812
25653
|
if (!errorAction.resolved) {
|
24813
|
-
|
25654
|
+
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
25655
|
}
|
24815
25656
|
}
|
24816
25657
|
};
|
@@ -24890,7 +25731,7 @@
|
|
24890
25731
|
return defaultPathway;
|
24891
25732
|
};
|
24892
25733
|
_proto.clonePathways = function clonePathways(pathwayClones) {
|
24893
|
-
var
|
25734
|
+
var _this2 = this;
|
24894
25735
|
var levels = this.levels;
|
24895
25736
|
if (!levels) {
|
24896
25737
|
return;
|
@@ -24906,7 +25747,7 @@
|
|
24906
25747
|
})) {
|
24907
25748
|
return;
|
24908
25749
|
}
|
24909
|
-
var clonedVariants =
|
25750
|
+
var clonedVariants = _this2.getLevelsForPathway(baseId).map(function (baseLevel) {
|
24910
25751
|
var attributes = new AttrList(baseLevel.attrs);
|
24911
25752
|
attributes['PATHWAY-ID'] = cloneId;
|
24912
25753
|
var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
|
@@ -24943,12 +25784,12 @@
|
|
24943
25784
|
return clonedLevel;
|
24944
25785
|
});
|
24945
25786
|
levels.push.apply(levels, clonedVariants);
|
24946
|
-
cloneRenditionGroups(
|
24947
|
-
cloneRenditionGroups(
|
25787
|
+
cloneRenditionGroups(_this2.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
|
25788
|
+
cloneRenditionGroups(_this2.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
|
24948
25789
|
});
|
24949
25790
|
};
|
24950
25791
|
_proto.loadSteeringManifest = function loadSteeringManifest(uri) {
|
24951
|
-
var
|
25792
|
+
var _this3 = this;
|
24952
25793
|
var config = this.hls.config;
|
24953
25794
|
var Loader = config.loader;
|
24954
25795
|
if (this.loader) {
|
@@ -24983,87 +25824,87 @@
|
|
24983
25824
|
};
|
24984
25825
|
var callbacks = {
|
24985
25826
|
onSuccess: function onSuccess(response, stats, context, networkDetails) {
|
24986
|
-
|
25827
|
+
_this3.log("Loaded steering manifest: \"" + url + "\"");
|
24987
25828
|
var steeringData = response.data;
|
24988
|
-
if (steeringData.VERSION !== 1) {
|
24989
|
-
|
25829
|
+
if ((steeringData == null ? void 0 : steeringData.VERSION) !== 1) {
|
25830
|
+
_this3.log("Steering VERSION " + steeringData.VERSION + " not supported!");
|
24990
25831
|
return;
|
24991
25832
|
}
|
24992
|
-
|
24993
|
-
|
25833
|
+
_this3.updated = performance.now();
|
25834
|
+
_this3.timeToLoad = steeringData.TTL;
|
24994
25835
|
var reloadUri = steeringData['RELOAD-URI'],
|
24995
25836
|
pathwayClones = steeringData['PATHWAY-CLONES'],
|
24996
25837
|
pathwayPriority = steeringData['PATHWAY-PRIORITY'];
|
24997
25838
|
if (reloadUri) {
|
24998
25839
|
try {
|
24999
|
-
|
25840
|
+
_this3.uri = new self.URL(reloadUri, url).href;
|
25000
25841
|
} catch (error) {
|
25001
|
-
|
25002
|
-
|
25842
|
+
_this3.enabled = false;
|
25843
|
+
_this3.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
|
25003
25844
|
return;
|
25004
25845
|
}
|
25005
25846
|
}
|
25006
|
-
|
25847
|
+
_this3.scheduleRefresh(_this3.uri || context.url);
|
25007
25848
|
if (pathwayClones) {
|
25008
|
-
|
25849
|
+
_this3.clonePathways(pathwayClones);
|
25009
25850
|
}
|
25010
25851
|
var loadedSteeringData = {
|
25011
25852
|
steeringManifest: steeringData,
|
25012
25853
|
url: url.toString()
|
25013
25854
|
};
|
25014
|
-
|
25855
|
+
_this3.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
|
25015
25856
|
if (pathwayPriority) {
|
25016
|
-
|
25857
|
+
_this3.updatePathwayPriority(pathwayPriority);
|
25017
25858
|
}
|
25018
25859
|
},
|
25019
25860
|
onError: function onError(error, context, networkDetails, stats) {
|
25020
|
-
|
25021
|
-
|
25861
|
+
_this3.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
|
25862
|
+
_this3.stopLoad();
|
25022
25863
|
if (error.code === 410) {
|
25023
|
-
|
25024
|
-
|
25864
|
+
_this3.enabled = false;
|
25865
|
+
_this3.log("Steering manifest " + context.url + " no longer available");
|
25025
25866
|
return;
|
25026
25867
|
}
|
25027
|
-
var ttl =
|
25868
|
+
var ttl = _this3.timeToLoad * 1000;
|
25028
25869
|
if (error.code === 429) {
|
25029
|
-
var loader =
|
25870
|
+
var loader = _this3.loader;
|
25030
25871
|
if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
|
25031
25872
|
var retryAfter = loader.getResponseHeader('Retry-After');
|
25032
25873
|
if (retryAfter) {
|
25033
25874
|
ttl = parseFloat(retryAfter) * 1000;
|
25034
25875
|
}
|
25035
25876
|
}
|
25036
|
-
|
25877
|
+
_this3.log("Steering manifest " + context.url + " rate limited");
|
25037
25878
|
return;
|
25038
25879
|
}
|
25039
|
-
|
25880
|
+
_this3.scheduleRefresh(_this3.uri || context.url, ttl);
|
25040
25881
|
},
|
25041
25882
|
onTimeout: function onTimeout(stats, context, networkDetails) {
|
25042
|
-
|
25043
|
-
|
25883
|
+
_this3.log("Timeout loading steering manifest (" + context.url + ")");
|
25884
|
+
_this3.scheduleRefresh(_this3.uri || context.url);
|
25044
25885
|
}
|
25045
25886
|
};
|
25046
25887
|
this.log("Requesting steering manifest: " + url);
|
25047
25888
|
this.loader.load(context, loaderConfig, callbacks);
|
25048
25889
|
};
|
25049
25890
|
_proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
|
25050
|
-
var
|
25891
|
+
var _this4 = this;
|
25051
25892
|
if (ttlMs === void 0) {
|
25052
25893
|
ttlMs = this.timeToLoad * 1000;
|
25053
25894
|
}
|
25054
25895
|
this.clearTimeout();
|
25055
25896
|
this.reloadTimer = self.setTimeout(function () {
|
25056
|
-
var
|
25057
|
-
var media = (
|
25897
|
+
var _this4$hls;
|
25898
|
+
var media = (_this4$hls = _this4.hls) == null ? void 0 : _this4$hls.media;
|
25058
25899
|
if (media && !media.ended) {
|
25059
|
-
|
25900
|
+
_this4.loadSteeringManifest(uri);
|
25060
25901
|
return;
|
25061
25902
|
}
|
25062
|
-
|
25903
|
+
_this4.scheduleRefresh(uri, _this4.timeToLoad * 1000);
|
25063
25904
|
}, ttlMs);
|
25064
25905
|
};
|
25065
25906
|
return ContentSteeringController;
|
25066
|
-
}();
|
25907
|
+
}(Logger);
|
25067
25908
|
function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
|
25068
25909
|
if (!tracks) {
|
25069
25910
|
return;
|
@@ -25963,7 +26804,7 @@
|
|
25963
26804
|
/**
|
25964
26805
|
* @ignore
|
25965
26806
|
*/
|
25966
|
-
function mergeConfig(defaultConfig, userConfig) {
|
26807
|
+
function mergeConfig(defaultConfig, userConfig, logger) {
|
25967
26808
|
if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
|
25968
26809
|
throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
|
25969
26810
|
}
|
@@ -26033,7 +26874,7 @@
|
|
26033
26874
|
/**
|
26034
26875
|
* @ignore
|
26035
26876
|
*/
|
26036
|
-
function enableStreamingMode(config) {
|
26877
|
+
function enableStreamingMode(config, logger) {
|
26037
26878
|
var currentLoader = config.loader;
|
26038
26879
|
if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
|
26039
26880
|
// If a developer has configured their own loader, respect that choice
|
@@ -26050,12 +26891,11 @@
|
|
26050
26891
|
}
|
26051
26892
|
}
|
26052
26893
|
|
26053
|
-
var chromeOrFirefox;
|
26054
26894
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
26055
26895
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
26056
26896
|
function LevelController(hls, contentSteeringController) {
|
26057
26897
|
var _this;
|
26058
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
26898
|
+
_this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
|
26059
26899
|
_this._levels = [];
|
26060
26900
|
_this._firstLevel = -1;
|
26061
26901
|
_this._maxAutoLevel = -1;
|
@@ -26124,21 +26964,13 @@
|
|
26124
26964
|
var videoCodecFound = false;
|
26125
26965
|
var audioCodecFound = false;
|
26126
26966
|
data.levels.forEach(function (levelParsed) {
|
26127
|
-
var
|
26967
|
+
var _videoCodec;
|
26128
26968
|
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
26969
|
var audioCodec = levelParsed.audioCodec,
|
26133
26970
|
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
26971
|
if (audioCodec) {
|
26141
|
-
|
26972
|
+
// Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
|
26973
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
26142
26974
|
}
|
26143
26975
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
26144
26976
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -26746,6 +27578,8 @@
|
|
26746
27578
|
}
|
26747
27579
|
return this.loadKeyEME(keyInfo, frag);
|
26748
27580
|
case 'AES-128':
|
27581
|
+
case 'AES-256':
|
27582
|
+
case 'AES-256-CTR':
|
26749
27583
|
return this.loadKeyHTTP(keyInfo, frag);
|
26750
27584
|
default:
|
26751
27585
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -26885,21 +27719,26 @@
|
|
26885
27719
|
var MAX_START_GAP_JUMP = 2.0;
|
26886
27720
|
var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
|
26887
27721
|
var SKIP_BUFFER_RANGE_START = 0.05;
|
26888
|
-
var GapController = /*#__PURE__*/function () {
|
27722
|
+
var GapController = /*#__PURE__*/function (_Logger) {
|
27723
|
+
_inheritsLoose(GapController, _Logger);
|
26889
27724
|
function GapController(config, media, fragmentTracker, hls) {
|
26890
|
-
|
26891
|
-
this.
|
26892
|
-
|
26893
|
-
|
26894
|
-
|
26895
|
-
|
26896
|
-
|
26897
|
-
|
26898
|
-
|
26899
|
-
|
26900
|
-
|
26901
|
-
|
26902
|
-
|
27725
|
+
var _this;
|
27726
|
+
_this = _Logger.call(this, 'gap-controller', hls.logger) || this;
|
27727
|
+
_this.config = void 0;
|
27728
|
+
_this.media = null;
|
27729
|
+
_this.fragmentTracker = void 0;
|
27730
|
+
_this.hls = void 0;
|
27731
|
+
_this.nudgeRetry = 0;
|
27732
|
+
_this.stallReported = false;
|
27733
|
+
_this.stalled = null;
|
27734
|
+
_this.moved = false;
|
27735
|
+
_this.seeking = false;
|
27736
|
+
_this.ended = 0;
|
27737
|
+
_this.config = config;
|
27738
|
+
_this.media = media;
|
27739
|
+
_this.fragmentTracker = fragmentTracker;
|
27740
|
+
_this.hls = hls;
|
27741
|
+
return _this;
|
26903
27742
|
}
|
26904
27743
|
var _proto = GapController.prototype;
|
26905
27744
|
_proto.destroy = function destroy() {
|
@@ -26914,7 +27753,7 @@
|
|
26914
27753
|
*
|
26915
27754
|
* @param lastCurrentTime - Previously read playhead position
|
26916
27755
|
*/;
|
26917
|
-
_proto.poll = function poll(lastCurrentTime, activeFrag) {
|
27756
|
+
_proto.poll = function poll(lastCurrentTime, activeFrag, levelDetails, state) {
|
26918
27757
|
var config = this.config,
|
26919
27758
|
media = this.media,
|
26920
27759
|
stalled = this.stalled;
|
@@ -26929,6 +27768,7 @@
|
|
26929
27768
|
|
26930
27769
|
// The playhead is moving, no-op
|
26931
27770
|
if (currentTime !== lastCurrentTime) {
|
27771
|
+
this.ended = 0;
|
26932
27772
|
this.moved = true;
|
26933
27773
|
if (!seeking) {
|
26934
27774
|
this.nudgeRetry = 0;
|
@@ -26937,7 +27777,7 @@
|
|
26937
27777
|
// The playhead is now moving, but was previously stalled
|
26938
27778
|
if (this.stallReported) {
|
26939
27779
|
var _stalledDuration = self.performance.now() - stalled;
|
26940
|
-
|
27780
|
+
this.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
|
26941
27781
|
this.stallReported = false;
|
26942
27782
|
}
|
26943
27783
|
this.stalled = null;
|
@@ -26973,7 +27813,6 @@
|
|
26973
27813
|
// Skip start gaps if we haven't played, but the last poll detected the start of a stall
|
26974
27814
|
// The addition poll gives the browser a chance to jump the gap for us
|
26975
27815
|
if (!this.moved && this.stalled !== null) {
|
26976
|
-
var _level$details;
|
26977
27816
|
// There is no playable buffer (seeked, waiting for buffer)
|
26978
27817
|
var isBuffered = bufferInfo.len > 0;
|
26979
27818
|
if (!isBuffered && !nextStart) {
|
@@ -26985,9 +27824,8 @@
|
|
26985
27824
|
// When joining a live stream with audio tracks, account for live playlist window sliding by allowing
|
26986
27825
|
// a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
|
26987
27826
|
// 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;
|
27827
|
+
var isLive = !!(levelDetails != null && levelDetails.live);
|
27828
|
+
var maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
|
26991
27829
|
var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
|
26992
27830
|
if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
|
26993
27831
|
if (!media.paused) {
|
@@ -27005,6 +27843,17 @@
|
|
27005
27843
|
}
|
27006
27844
|
var stalledDuration = tnow - stalled;
|
27007
27845
|
if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
|
27846
|
+
// Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
|
27847
|
+
if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
|
27848
|
+
if (stalledDuration < 1000 || this.ended) {
|
27849
|
+
return;
|
27850
|
+
}
|
27851
|
+
this.ended = currentTime;
|
27852
|
+
this.hls.trigger(Events.MEDIA_ENDED, {
|
27853
|
+
stalled: true
|
27854
|
+
});
|
27855
|
+
return;
|
27856
|
+
}
|
27008
27857
|
// Report stalling after trying to fix
|
27009
27858
|
this._reportStall(bufferInfo);
|
27010
27859
|
if (!this.media) {
|
@@ -27046,7 +27895,7 @@
|
|
27046
27895
|
// needs to cross some sort of threshold covering all source-buffers content
|
27047
27896
|
// to start playing properly.
|
27048
27897
|
if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
|
27049
|
-
|
27898
|
+
this.warn('Trying to nudge playhead over buffer-hole');
|
27050
27899
|
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
|
27051
27900
|
// We only try to jump the hole if it's under the configured size
|
27052
27901
|
// Reset stalled so to rearm watchdog timer
|
@@ -27068,7 +27917,7 @@
|
|
27068
27917
|
// Report stalled error once
|
27069
27918
|
this.stallReported = true;
|
27070
27919
|
var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
|
27071
|
-
|
27920
|
+
this.warn(error.message);
|
27072
27921
|
hls.trigger(Events.ERROR, {
|
27073
27922
|
type: ErrorTypes.MEDIA_ERROR,
|
27074
27923
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27132,7 +27981,7 @@
|
|
27132
27981
|
}
|
27133
27982
|
}
|
27134
27983
|
var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
|
27135
|
-
|
27984
|
+
this.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
|
27136
27985
|
this.moved = true;
|
27137
27986
|
this.stalled = null;
|
27138
27987
|
media.currentTime = targetTime;
|
@@ -27171,7 +28020,7 @@
|
|
27171
28020
|
var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
|
27172
28021
|
// playback stalled in buffered area ... let's nudge currentTime to try to overcome this
|
27173
28022
|
var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
|
27174
|
-
|
28023
|
+
this.warn(error.message);
|
27175
28024
|
media.currentTime = targetTime;
|
27176
28025
|
hls.trigger(Events.ERROR, {
|
27177
28026
|
type: ErrorTypes.MEDIA_ERROR,
|
@@ -27181,7 +28030,7 @@
|
|
27181
28030
|
});
|
27182
28031
|
} else {
|
27183
28032
|
var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
|
27184
|
-
|
28033
|
+
this.error(_error.message);
|
27185
28034
|
hls.trigger(Events.ERROR, {
|
27186
28035
|
type: ErrorTypes.MEDIA_ERROR,
|
27187
28036
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27191,14 +28040,14 @@
|
|
27191
28040
|
}
|
27192
28041
|
};
|
27193
28042
|
return GapController;
|
27194
|
-
}();
|
28043
|
+
}(Logger);
|
27195
28044
|
|
27196
28045
|
var TICK_INTERVAL = 100; // how often to tick in ms
|
27197
28046
|
var StreamController = /*#__PURE__*/function (_BaseStreamController) {
|
27198
28047
|
_inheritsLoose(StreamController, _BaseStreamController);
|
27199
28048
|
function StreamController(hls, fragmentTracker, keyLoader) {
|
27200
28049
|
var _this;
|
27201
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
28050
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
|
27202
28051
|
_this.audioCodecSwap = false;
|
27203
28052
|
_this.gapController = null;
|
27204
28053
|
_this.level = -1;
|
@@ -27206,27 +28055,43 @@
|
|
27206
28055
|
_this.altAudio = false;
|
27207
28056
|
_this.audioOnly = false;
|
27208
28057
|
_this.fragPlaying = null;
|
27209
|
-
_this.onvplaying = null;
|
27210
|
-
_this.onvseeked = null;
|
27211
28058
|
_this.fragLastKbps = 0;
|
27212
28059
|
_this.couldBacktrack = false;
|
27213
28060
|
_this.backtrackFragment = null;
|
27214
28061
|
_this.audioCodecSwitch = false;
|
27215
28062
|
_this.videoBuffer = null;
|
27216
|
-
_this.
|
28063
|
+
_this.onMediaPlaying = function () {
|
28064
|
+
// tick to speed up FRAG_CHANGED triggering
|
28065
|
+
_this.tick();
|
28066
|
+
};
|
28067
|
+
_this.onMediaSeeked = function () {
|
28068
|
+
var media = _this.media;
|
28069
|
+
var currentTime = media ? media.currentTime : null;
|
28070
|
+
if (isFiniteNumber(currentTime)) {
|
28071
|
+
_this.log("Media seeked to " + currentTime.toFixed(3));
|
28072
|
+
}
|
28073
|
+
|
28074
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
28075
|
+
var bufferInfo = _this.getMainFwdBufferInfo();
|
28076
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
28077
|
+
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
28078
|
+
return;
|
28079
|
+
}
|
28080
|
+
|
28081
|
+
// tick to speed up FRAG_CHANGED triggering
|
28082
|
+
_this.tick();
|
28083
|
+
};
|
28084
|
+
_this.registerListeners();
|
27217
28085
|
return _this;
|
27218
28086
|
}
|
27219
28087
|
var _proto = StreamController.prototype;
|
27220
|
-
_proto.
|
28088
|
+
_proto.registerListeners = function registerListeners() {
|
28089
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
27221
28090
|
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
28091
|
hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27226
28092
|
hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
|
27227
28093
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27228
28094
|
hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27229
|
-
hls.on(Events.ERROR, this.onError, this);
|
27230
28095
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27231
28096
|
hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27232
28097
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27234,15 +28099,12 @@
|
|
27234
28099
|
hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
|
27235
28100
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27236
28101
|
};
|
27237
|
-
_proto.
|
28102
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
28103
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
27238
28104
|
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
28105
|
hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27243
28106
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27244
28107
|
hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27245
|
-
hls.off(Events.ERROR, this.onError, this);
|
27246
28108
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27247
28109
|
hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27248
28110
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27251,7 +28113,9 @@
|
|
27251
28113
|
hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27252
28114
|
};
|
27253
28115
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
27254
|
-
|
28116
|
+
// @ts-ignore
|
28117
|
+
this.onMediaPlaying = this.onMediaSeeked = null;
|
28118
|
+
this.unregisterListeners();
|
27255
28119
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
27256
28120
|
};
|
27257
28121
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -27361,7 +28225,7 @@
|
|
27361
28225
|
if (this.altAudio && this.audioOnly) {
|
27362
28226
|
return;
|
27363
28227
|
}
|
27364
|
-
if (!(levels != null && levels[level])) {
|
28228
|
+
if (!this.buffering || !(levels != null && levels[level])) {
|
27365
28229
|
return;
|
27366
28230
|
}
|
27367
28231
|
var levelInfo = levels[level];
|
@@ -27567,18 +28431,15 @@
|
|
27567
28431
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
27568
28432
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
27569
28433
|
var media = data.media;
|
27570
|
-
|
27571
|
-
|
27572
|
-
media.addEventListener('playing', this.onvplaying);
|
27573
|
-
media.addEventListener('seeked', this.onvseeked);
|
28434
|
+
media.addEventListener('playing', this.onMediaPlaying);
|
28435
|
+
media.addEventListener('seeked', this.onMediaSeeked);
|
27574
28436
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
27575
28437
|
};
|
27576
28438
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
27577
28439
|
var media = this.media;
|
27578
|
-
if (media
|
27579
|
-
media.removeEventListener('playing', this.
|
27580
|
-
media.removeEventListener('seeked', this.
|
27581
|
-
this.onvplaying = this.onvseeked = null;
|
28440
|
+
if (media) {
|
28441
|
+
media.removeEventListener('playing', this.onMediaPlaying);
|
28442
|
+
media.removeEventListener('seeked', this.onMediaSeeked);
|
27582
28443
|
this.videoBuffer = null;
|
27583
28444
|
}
|
27584
28445
|
this.fragPlaying = null;
|
@@ -27588,27 +28449,6 @@
|
|
27588
28449
|
}
|
27589
28450
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
27590
28451
|
};
|
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
28452
|
_proto.onManifestLoading = function onManifestLoading() {
|
27613
28453
|
// reset buffer on manifest loading
|
27614
28454
|
this.log('Trigger BUFFER_RESET');
|
@@ -27889,8 +28729,10 @@
|
|
27889
28729
|
}
|
27890
28730
|
if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
|
27891
28731
|
// Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
|
27892
|
-
var
|
27893
|
-
|
28732
|
+
var state = this.state;
|
28733
|
+
var activeFrag = state !== State.IDLE ? this.fragCurrent : null;
|
28734
|
+
var levelDetails = this.getLevelDetails();
|
28735
|
+
gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
|
27894
28736
|
}
|
27895
28737
|
this.lastCurrentTime = media.currentTime;
|
27896
28738
|
};
|
@@ -28355,9 +29197,12 @@
|
|
28355
29197
|
* The configuration object provided on player instantiation.
|
28356
29198
|
*/
|
28357
29199
|
this.userConfig = void 0;
|
29200
|
+
/**
|
29201
|
+
* The logger functions used by this player instance, configured on player instantiation.
|
29202
|
+
*/
|
29203
|
+
this.logger = void 0;
|
28358
29204
|
this.coreComponents = void 0;
|
28359
29205
|
this.networkControllers = void 0;
|
28360
|
-
this.started = false;
|
28361
29206
|
this._emitter = new EventEmitter();
|
28362
29207
|
this._autoLevelCapping = -1;
|
28363
29208
|
this._maxHdcpLevel = null;
|
@@ -28374,11 +29219,11 @@
|
|
28374
29219
|
this._media = null;
|
28375
29220
|
this.url = null;
|
28376
29221
|
this.triggeringException = void 0;
|
28377
|
-
enableLogs(userConfig.debug || false, 'Hls instance');
|
28378
|
-
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
|
29222
|
+
var logger = this.logger = enableLogs(userConfig.debug || false, 'Hls instance');
|
29223
|
+
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig, logger);
|
28379
29224
|
this.userConfig = userConfig;
|
28380
29225
|
if (config.progressive) {
|
28381
|
-
enableStreamingMode(config);
|
29226
|
+
enableStreamingMode(config, logger);
|
28382
29227
|
}
|
28383
29228
|
|
28384
29229
|
// core controllers and network loaders
|
@@ -28486,7 +29331,7 @@
|
|
28486
29331
|
try {
|
28487
29332
|
return this.emit(event, event, eventObject);
|
28488
29333
|
} catch (error) {
|
28489
|
-
logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
29334
|
+
this.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
28490
29335
|
// Prevent recursion in error event handlers that throw #5497
|
28491
29336
|
if (!this.triggeringException) {
|
28492
29337
|
this.triggeringException = true;
|
@@ -28512,7 +29357,7 @@
|
|
28512
29357
|
* Dispose of the instance
|
28513
29358
|
*/;
|
28514
29359
|
_proto.destroy = function destroy() {
|
28515
|
-
logger.log('destroy');
|
29360
|
+
this.logger.log('destroy');
|
28516
29361
|
this.trigger(Events.DESTROYING, undefined);
|
28517
29362
|
this.detachMedia();
|
28518
29363
|
this.removeAllListeners();
|
@@ -28537,7 +29382,7 @@
|
|
28537
29382
|
* Attaches Hls.js to a media element
|
28538
29383
|
*/;
|
28539
29384
|
_proto.attachMedia = function attachMedia(media) {
|
28540
|
-
logger.log('attachMedia');
|
29385
|
+
this.logger.log('attachMedia');
|
28541
29386
|
this._media = media;
|
28542
29387
|
this.trigger(Events.MEDIA_ATTACHING, {
|
28543
29388
|
media: media
|
@@ -28548,7 +29393,7 @@
|
|
28548
29393
|
* Detach Hls.js from the media
|
28549
29394
|
*/;
|
28550
29395
|
_proto.detachMedia = function detachMedia() {
|
28551
|
-
logger.log('detachMedia');
|
29396
|
+
this.logger.log('detachMedia');
|
28552
29397
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
28553
29398
|
this._media = null;
|
28554
29399
|
}
|
@@ -28565,7 +29410,7 @@
|
|
28565
29410
|
});
|
28566
29411
|
this._autoLevelCapping = -1;
|
28567
29412
|
this._maxHdcpLevel = null;
|
28568
|
-
logger.log("loadSource:" + loadingSource);
|
29413
|
+
this.logger.log("loadSource:" + loadingSource);
|
28569
29414
|
if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
|
28570
29415
|
this.detachMedia();
|
28571
29416
|
this.attachMedia(media);
|
@@ -28587,8 +29432,7 @@
|
|
28587
29432
|
if (startPosition === void 0) {
|
28588
29433
|
startPosition = -1;
|
28589
29434
|
}
|
28590
|
-
logger.log("startLoad(" + startPosition + ")");
|
28591
|
-
this.started = true;
|
29435
|
+
this.logger.log("startLoad(" + startPosition + ")");
|
28592
29436
|
this.networkControllers.forEach(function (controller) {
|
28593
29437
|
controller.startLoad(startPosition);
|
28594
29438
|
});
|
@@ -28598,34 +29442,31 @@
|
|
28598
29442
|
* Stop loading of any stream data.
|
28599
29443
|
*/;
|
28600
29444
|
_proto.stopLoad = function stopLoad() {
|
28601
|
-
logger.log('stopLoad');
|
28602
|
-
this.started = false;
|
29445
|
+
this.logger.log('stopLoad');
|
28603
29446
|
this.networkControllers.forEach(function (controller) {
|
28604
29447
|
controller.stopLoad();
|
28605
29448
|
});
|
28606
29449
|
}
|
28607
29450
|
|
28608
29451
|
/**
|
28609
|
-
* Resumes stream controller segment loading
|
29452
|
+
* Resumes stream controller segment loading after `pauseBuffering` has been called.
|
28610
29453
|
*/;
|
28611
29454
|
_proto.resumeBuffering = function resumeBuffering() {
|
28612
|
-
|
28613
|
-
|
28614
|
-
|
28615
|
-
|
28616
|
-
|
28617
|
-
});
|
28618
|
-
}
|
29455
|
+
this.networkControllers.forEach(function (controller) {
|
29456
|
+
if (controller.resumeBuffering) {
|
29457
|
+
controller.resumeBuffering();
|
29458
|
+
}
|
29459
|
+
});
|
28619
29460
|
}
|
28620
29461
|
|
28621
29462
|
/**
|
28622
|
-
*
|
29463
|
+
* Prevents stream controller from loading new segments until `resumeBuffering` is called.
|
28623
29464
|
* This allows for media buffering to be paused without interupting playlist loading.
|
28624
29465
|
*/;
|
28625
29466
|
_proto.pauseBuffering = function pauseBuffering() {
|
28626
29467
|
this.networkControllers.forEach(function (controller) {
|
28627
|
-
if (
|
28628
|
-
controller.
|
29468
|
+
if (controller.pauseBuffering) {
|
29469
|
+
controller.pauseBuffering();
|
28629
29470
|
}
|
28630
29471
|
});
|
28631
29472
|
}
|
@@ -28634,7 +29475,7 @@
|
|
28634
29475
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
28635
29476
|
*/;
|
28636
29477
|
_proto.swapAudioCodec = function swapAudioCodec() {
|
28637
|
-
logger.log('swapAudioCodec');
|
29478
|
+
this.logger.log('swapAudioCodec');
|
28638
29479
|
this.streamController.swapAudioCodec();
|
28639
29480
|
}
|
28640
29481
|
|
@@ -28645,7 +29486,7 @@
|
|
28645
29486
|
* Automatic recovery of media-errors by this process is configurable.
|
28646
29487
|
*/;
|
28647
29488
|
_proto.recoverMediaError = function recoverMediaError() {
|
28648
|
-
logger.log('recoverMediaError');
|
29489
|
+
this.logger.log('recoverMediaError');
|
28649
29490
|
var media = this._media;
|
28650
29491
|
this.detachMedia();
|
28651
29492
|
if (media) {
|
@@ -28700,7 +29541,7 @@
|
|
28700
29541
|
* 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
29542
|
*/,
|
28702
29543
|
set: function set(newLevel) {
|
28703
|
-
logger.log("set currentLevel:" + newLevel);
|
29544
|
+
this.logger.log("set currentLevel:" + newLevel);
|
28704
29545
|
this.levelController.manualLevel = newLevel;
|
28705
29546
|
this.streamController.immediateLevelSwitch();
|
28706
29547
|
}
|
@@ -28721,7 +29562,7 @@
|
|
28721
29562
|
* @param newLevel - Pass -1 for automatic level selection
|
28722
29563
|
*/,
|
28723
29564
|
set: function set(newLevel) {
|
28724
|
-
logger.log("set nextLevel:" + newLevel);
|
29565
|
+
this.logger.log("set nextLevel:" + newLevel);
|
28725
29566
|
this.levelController.manualLevel = newLevel;
|
28726
29567
|
this.streamController.nextLevelSwitch();
|
28727
29568
|
}
|
@@ -28742,7 +29583,7 @@
|
|
28742
29583
|
* @param newLevel - Pass -1 for automatic level selection
|
28743
29584
|
*/,
|
28744
29585
|
set: function set(newLevel) {
|
28745
|
-
logger.log("set loadLevel:" + newLevel);
|
29586
|
+
this.logger.log("set loadLevel:" + newLevel);
|
28746
29587
|
this.levelController.manualLevel = newLevel;
|
28747
29588
|
}
|
28748
29589
|
|
@@ -28777,7 +29618,7 @@
|
|
28777
29618
|
* Sets "first-level", see getter.
|
28778
29619
|
*/,
|
28779
29620
|
set: function set(newLevel) {
|
28780
|
-
logger.log("set firstLevel:" + newLevel);
|
29621
|
+
this.logger.log("set firstLevel:" + newLevel);
|
28781
29622
|
this.levelController.firstLevel = newLevel;
|
28782
29623
|
}
|
28783
29624
|
|
@@ -28804,7 +29645,7 @@
|
|
28804
29645
|
* (determined from download of first segment)
|
28805
29646
|
*/,
|
28806
29647
|
set: function set(newLevel) {
|
28807
|
-
logger.log("set startLevel:" + newLevel);
|
29648
|
+
this.logger.log("set startLevel:" + newLevel);
|
28808
29649
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
28809
29650
|
if (newLevel !== -1) {
|
28810
29651
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -28857,7 +29698,7 @@
|
|
28857
29698
|
*/
|
28858
29699
|
function set(newLevel) {
|
28859
29700
|
if (this._autoLevelCapping !== newLevel) {
|
28860
|
-
logger.log("set autoLevelCapping:" + newLevel);
|
29701
|
+
this.logger.log("set autoLevelCapping:" + newLevel);
|
28861
29702
|
this._autoLevelCapping = newLevel;
|
28862
29703
|
this.levelController.checkMaxAutoUpdated();
|
28863
29704
|
}
|
@@ -29182,7 +30023,7 @@
|
|
29182
30023
|
* Get the video-dev/hls.js package version.
|
29183
30024
|
*/
|
29184
30025
|
function get() {
|
29185
|
-
return "1.5.
|
30026
|
+
return "1.5.5-0.canary.9978";
|
29186
30027
|
}
|
29187
30028
|
}, {
|
29188
30029
|
key: "Events",
|