hls.js 1.5.3 → 1.5.5-0.canary.9977
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/hls-demo.js +10 -0
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +1954 -1103
- package/dist/hls.js.d.ts +63 -50
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +1631 -784
- 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 +1428 -590
- 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 +1703 -866
- 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 +24 -22
- package/src/controller/audio-stream-controller.ts +16 -17
- 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 +27 -33
- package/src/controller/subtitle-stream-controller.ts +14 -15
- package/src/controller/subtitle-track-controller.ts +5 -3
- package/src/controller/timeline-controller.ts +23 -30
- package/src/crypt/aes-crypto.ts +21 -2
- package/src/crypt/decrypter-aes-mode.ts +4 -0
- package/src/crypt/decrypter.ts +32 -18
- package/src/crypt/fast-aes-key.ts +24 -5
- package/src/demux/audio/adts.ts +9 -4
- package/src/demux/sample-aes.ts +2 -0
- package/src/demux/transmuxer-interface.ts +4 -12
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +16 -3
- package/src/demux/tsdemuxer.ts +63 -37
- package/src/demux/video/avc-video-parser.ts +208 -119
- package/src/demux/video/base-video-parser.ts +134 -2
- package/src/demux/video/exp-golomb.ts +0 -208
- package/src/demux/video/hevc-video-parser.ts +746 -0
- package/src/events.ts +7 -0
- package/src/hls.ts +42 -34
- package/src/loader/fragment-loader.ts +9 -2
- package/src/loader/key-loader.ts +2 -0
- package/src/loader/level-key.ts +10 -9
- package/src/remux/mp4-generator.ts +196 -1
- package/src/remux/mp4-remuxer.ts +23 -7
- package/src/task-loop.ts +5 -2
- package/src/types/component-api.ts +2 -0
- package/src/types/demuxer.ts +3 -0
- package/src/types/events.ts +4 -0
- package/src/utils/codecs.ts +33 -4
- package/src/utils/encryption-methods-util.ts +21 -0
- package/src/utils/logger.ts +53 -24
- package/src/utils/mp4-tools.ts +28 -9
package/dist/hls.js
CHANGED
@@ -5,6 +5,21 @@
|
|
5
5
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Hls = factory());
|
6
6
|
})(this, (function () { 'use strict';
|
7
7
|
|
8
|
+
function _construct(t, e, r) {
|
9
|
+
if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
|
10
|
+
var o = [null];
|
11
|
+
o.push.apply(o, e);
|
12
|
+
var p = new (t.bind.apply(t, o))();
|
13
|
+
return r && _setPrototypeOf(p, r.prototype), p;
|
14
|
+
}
|
15
|
+
function _isNativeReflectConstruct() {
|
16
|
+
try {
|
17
|
+
var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
18
|
+
} catch (t) {}
|
19
|
+
return (_isNativeReflectConstruct = function () {
|
20
|
+
return !!t;
|
21
|
+
})();
|
22
|
+
}
|
8
23
|
function ownKeys(e, r) {
|
9
24
|
var t = Object.keys(e);
|
10
25
|
if (Object.getOwnPropertySymbols) {
|
@@ -103,32 +118,6 @@
|
|
103
118
|
};
|
104
119
|
return _setPrototypeOf(o, p);
|
105
120
|
}
|
106
|
-
function _isNativeReflectConstruct() {
|
107
|
-
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
108
|
-
if (Reflect.construct.sham) return false;
|
109
|
-
if (typeof Proxy === "function") return true;
|
110
|
-
try {
|
111
|
-
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
112
|
-
return true;
|
113
|
-
} catch (e) {
|
114
|
-
return false;
|
115
|
-
}
|
116
|
-
}
|
117
|
-
function _construct(Parent, args, Class) {
|
118
|
-
if (_isNativeReflectConstruct()) {
|
119
|
-
_construct = Reflect.construct.bind();
|
120
|
-
} else {
|
121
|
-
_construct = function _construct(Parent, args, Class) {
|
122
|
-
var a = [null];
|
123
|
-
a.push.apply(a, args);
|
124
|
-
var Constructor = Function.bind.apply(Parent, a);
|
125
|
-
var instance = new Constructor();
|
126
|
-
if (Class) _setPrototypeOf(instance, Class.prototype);
|
127
|
-
return instance;
|
128
|
-
};
|
129
|
-
}
|
130
|
-
return _construct.apply(null, arguments);
|
131
|
-
}
|
132
121
|
function _isNativeFunction(fn) {
|
133
122
|
try {
|
134
123
|
return Function.toString.call(fn).indexOf("[native code]") !== -1;
|
@@ -394,6 +383,7 @@
|
|
394
383
|
Events["MEDIA_ATTACHED"] = "hlsMediaAttached";
|
395
384
|
Events["MEDIA_DETACHING"] = "hlsMediaDetaching";
|
396
385
|
Events["MEDIA_DETACHED"] = "hlsMediaDetached";
|
386
|
+
Events["MEDIA_ENDED"] = "hlsMediaEnded";
|
397
387
|
Events["BUFFER_RESET"] = "hlsBufferReset";
|
398
388
|
Events["BUFFER_CODECS"] = "hlsBufferCodecs";
|
399
389
|
Events["BUFFER_CREATED"] = "hlsBufferCreated";
|
@@ -507,6 +497,21 @@
|
|
507
497
|
return ErrorDetails;
|
508
498
|
}({});
|
509
499
|
|
500
|
+
var Logger = function Logger(label, logger) {
|
501
|
+
this.trace = void 0;
|
502
|
+
this.debug = void 0;
|
503
|
+
this.log = void 0;
|
504
|
+
this.warn = void 0;
|
505
|
+
this.info = void 0;
|
506
|
+
this.error = void 0;
|
507
|
+
var lb = "[" + label + "]:";
|
508
|
+
this.trace = noop;
|
509
|
+
this.debug = logger.debug.bind(null, lb);
|
510
|
+
this.log = logger.log.bind(null, lb);
|
511
|
+
this.warn = logger.warn.bind(null, lb);
|
512
|
+
this.info = logger.info.bind(null, lb);
|
513
|
+
this.error = logger.error.bind(null, lb);
|
514
|
+
};
|
510
515
|
var noop = function noop() {};
|
511
516
|
var fakeLogger = {
|
512
517
|
trace: noop,
|
@@ -516,7 +521,9 @@
|
|
516
521
|
info: noop,
|
517
522
|
error: noop
|
518
523
|
};
|
519
|
-
|
524
|
+
function createLogger() {
|
525
|
+
return _extends({}, fakeLogger);
|
526
|
+
}
|
520
527
|
|
521
528
|
// let lastCallTime;
|
522
529
|
// function formatMsgWithTimeInfo(type, msg) {
|
@@ -527,38 +534,36 @@
|
|
527
534
|
// return msg;
|
528
535
|
// }
|
529
536
|
|
530
|
-
function consolePrintFn(type) {
|
537
|
+
function consolePrintFn(type, id) {
|
531
538
|
var func = self.console[type];
|
532
|
-
|
533
|
-
return func.bind(self.console, "[" + type + "] >");
|
534
|
-
}
|
535
|
-
return noop;
|
539
|
+
return func ? func.bind(self.console, (id ? '[' + id + '] ' : '') + "[" + type + "] >") : noop;
|
536
540
|
}
|
537
|
-
function
|
538
|
-
|
539
|
-
functions[_key - 1] = arguments[_key];
|
540
|
-
}
|
541
|
-
functions.forEach(function (type) {
|
542
|
-
exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);
|
543
|
-
});
|
541
|
+
function getLoggerFn(key, debugConfig, id) {
|
542
|
+
return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key, id);
|
544
543
|
}
|
545
|
-
|
544
|
+
var exportedLogger = createLogger();
|
545
|
+
function enableLogs(debugConfig, context, id) {
|
546
546
|
// check that console is available
|
547
|
+
var newLogger = createLogger();
|
547
548
|
if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
|
548
|
-
|
549
|
+
var keys = [
|
549
550
|
// Remove out from list here to hard-disable a log-level
|
550
551
|
// 'trace',
|
551
|
-
'debug', 'log', 'info', 'warn', 'error'
|
552
|
+
'debug', 'log', 'info', 'warn', 'error'];
|
553
|
+
keys.forEach(function (key) {
|
554
|
+
newLogger[key] = getLoggerFn(key, debugConfig, id);
|
555
|
+
});
|
552
556
|
// Some browsers don't allow to use bind on console object anyway
|
553
557
|
// fallback to default if needed
|
554
558
|
try {
|
555
|
-
|
559
|
+
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.5-0.canary.9977");
|
556
560
|
} catch (e) {
|
557
|
-
|
561
|
+
/* log fn threw an exception. All logger methods are no-ops. */
|
562
|
+
return createLogger();
|
558
563
|
}
|
559
|
-
} else {
|
560
|
-
exportedLogger = fakeLogger;
|
561
564
|
}
|
565
|
+
exportedLogger = newLogger;
|
566
|
+
return newLogger;
|
562
567
|
}
|
563
568
|
var logger = exportedLogger;
|
564
569
|
|
@@ -1253,6 +1258,26 @@
|
|
1253
1258
|
});
|
1254
1259
|
}
|
1255
1260
|
|
1261
|
+
var DecrypterAesMode = {
|
1262
|
+
cbc: 0,
|
1263
|
+
ctr: 1
|
1264
|
+
};
|
1265
|
+
|
1266
|
+
function isFullSegmentEncryption(method) {
|
1267
|
+
return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
|
1268
|
+
}
|
1269
|
+
function getAesModeFromFullSegmentMethod(method) {
|
1270
|
+
switch (method) {
|
1271
|
+
case 'AES-128':
|
1272
|
+
case 'AES-256':
|
1273
|
+
return DecrypterAesMode.cbc;
|
1274
|
+
case 'AES-256-CTR':
|
1275
|
+
return DecrypterAesMode.ctr;
|
1276
|
+
default:
|
1277
|
+
throw new Error("invalid full segment method " + method);
|
1278
|
+
}
|
1279
|
+
}
|
1280
|
+
|
1256
1281
|
/** returns `undefined` is `self` is missing, e.g. in node */
|
1257
1282
|
var optionalSelf = typeof self !== 'undefined' ? self : undefined;
|
1258
1283
|
|
@@ -1774,6 +1799,12 @@
|
|
1774
1799
|
var val = readSint32(buffer, offset);
|
1775
1800
|
return val < 0 ? 4294967296 + val : val;
|
1776
1801
|
}
|
1802
|
+
function readUint64(buffer, offset) {
|
1803
|
+
var result = readUint32(buffer, offset);
|
1804
|
+
result *= Math.pow(2, 32);
|
1805
|
+
result += readUint32(buffer, offset + 4);
|
1806
|
+
return result;
|
1807
|
+
}
|
1777
1808
|
function readSint32(buffer, offset) {
|
1778
1809
|
return buffer[offset] << 24 | buffer[offset + 1] << 16 | buffer[offset + 2] << 8 | buffer[offset + 3];
|
1779
1810
|
}
|
@@ -1836,15 +1867,14 @@
|
|
1836
1867
|
var index = 8;
|
1837
1868
|
var timescale = readUint32(sidx, index);
|
1838
1869
|
index += 4;
|
1839
|
-
|
1840
|
-
// TODO: parse earliestPresentationTime and firstOffset
|
1841
|
-
// usually zero in our case
|
1842
1870
|
var earliestPresentationTime = 0;
|
1843
1871
|
var firstOffset = 0;
|
1844
1872
|
if (version === 0) {
|
1845
|
-
index +=
|
1873
|
+
earliestPresentationTime = readUint32(sidx, index += 4);
|
1874
|
+
firstOffset = readUint32(sidx, index += 4);
|
1846
1875
|
} else {
|
1847
|
-
index +=
|
1876
|
+
earliestPresentationTime = readUint64(sidx, index += 8);
|
1877
|
+
firstOffset = readUint64(sidx, index += 8);
|
1848
1878
|
}
|
1849
1879
|
|
1850
1880
|
// skip reserved
|
@@ -2294,17 +2324,24 @@
|
|
2294
2324
|
}
|
2295
2325
|
if (videoDuration === 0 && audioDuration === 0) {
|
2296
2326
|
// If duration samples are not available in the traf use sidx subsegment_duration
|
2327
|
+
var sidxMinStart = Infinity;
|
2328
|
+
var sidxMaxEnd = 0;
|
2297
2329
|
var sidxDuration = 0;
|
2298
2330
|
var sidxs = findBox(data, ['sidx']);
|
2299
2331
|
for (var _i2 = 0; _i2 < sidxs.length; _i2++) {
|
2300
2332
|
var sidx = parseSegmentIndex(sidxs[_i2]);
|
2301
2333
|
if (sidx != null && sidx.references) {
|
2302
|
-
|
2334
|
+
sidxMinStart = Math.min(sidxMinStart, sidx.earliestPresentationTime / sidx.timescale);
|
2335
|
+
var subSegmentDuration = sidx.references.reduce(function (dur, ref) {
|
2303
2336
|
return dur + ref.info.duration || 0;
|
2304
2337
|
}, 0);
|
2338
|
+
sidxMaxEnd = Math.max(sidxMaxEnd, subSegmentDuration + sidx.earliestPresentationTime / sidx.timescale);
|
2339
|
+
sidxDuration = sidxMaxEnd - sidxMinStart;
|
2305
2340
|
}
|
2306
2341
|
}
|
2307
|
-
|
2342
|
+
if (sidxDuration && isFiniteNumber(sidxDuration)) {
|
2343
|
+
return sidxDuration;
|
2344
|
+
}
|
2308
2345
|
}
|
2309
2346
|
if (videoDuration) {
|
2310
2347
|
return videoDuration;
|
@@ -2911,13 +2948,13 @@
|
|
2911
2948
|
this.keyFormatVersions = formatversions;
|
2912
2949
|
this.iv = iv;
|
2913
2950
|
this.encrypted = method ? method !== 'NONE' : false;
|
2914
|
-
this.isCommonEncryption = this.encrypted && method
|
2951
|
+
this.isCommonEncryption = this.encrypted && !isFullSegmentEncryption(method);
|
2915
2952
|
}
|
2916
2953
|
var _proto = LevelKey.prototype;
|
2917
2954
|
_proto.isSupported = function isSupported() {
|
2918
2955
|
// If it's Segment encryption or No encryption, just select that key system
|
2919
2956
|
if (this.method) {
|
2920
|
-
if (this.method
|
2957
|
+
if (isFullSegmentEncryption(this.method) || this.method === 'NONE') {
|
2921
2958
|
return true;
|
2922
2959
|
}
|
2923
2960
|
if (this.keyFormat === 'identity') {
|
@@ -2939,14 +2976,13 @@
|
|
2939
2976
|
if (!this.encrypted || !this.uri) {
|
2940
2977
|
return null;
|
2941
2978
|
}
|
2942
|
-
if (this.method
|
2979
|
+
if (isFullSegmentEncryption(this.method) && this.uri && !this.iv) {
|
2943
2980
|
if (typeof sn !== 'number') {
|
2944
2981
|
// We are fetching decryption data for a initialization segment
|
2945
|
-
// If the segment was encrypted with AES-128
|
2982
|
+
// If the segment was encrypted with AES-128/256
|
2946
2983
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
2947
|
-
|
2948
|
-
|
2949
|
-
}
|
2984
|
+
logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
|
2985
|
+
|
2950
2986
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
2951
2987
|
sn = 0;
|
2952
2988
|
}
|
@@ -3240,23 +3276,28 @@
|
|
3240
3276
|
if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
|
3241
3277
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
|
3242
3278
|
}
|
3243
|
-
|
3244
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3245
|
-
// some browsers will report that fLaC is supported then fail.
|
3246
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3247
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
|
3248
3283
|
flac: ['flac', 'fLaC', 'FLAC'],
|
3249
|
-
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']
|
3250
3288
|
}[lowerCaseCodec];
|
3251
3289
|
for (var i = 0; i < codecsToCheck.length; i++) {
|
3290
|
+
var _getMediaSource;
|
3252
3291
|
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
|
3253
3292
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
3254
3293
|
return codecsToCheck[i];
|
3294
|
+
} else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
|
3295
|
+
return '';
|
3255
3296
|
}
|
3256
3297
|
}
|
3257
3298
|
return lowerCaseCodec;
|
3258
3299
|
}
|
3259
|
-
var AUDIO_CODEC_REGEXP = /flac|opus/i;
|
3300
|
+
var AUDIO_CODEC_REGEXP = /flac|opus|mp4a\.40\.34/i;
|
3260
3301
|
function getCodecCompatibleName(codec, preferManagedMediaSource) {
|
3261
3302
|
if (preferManagedMediaSource === void 0) {
|
3262
3303
|
preferManagedMediaSource = true;
|
@@ -3284,6 +3325,18 @@
|
|
3284
3325
|
}
|
3285
3326
|
return codec;
|
3286
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
|
+
}
|
3287
3340
|
|
3288
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;
|
3289
3342
|
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
|
@@ -4947,8 +5000,43 @@
|
|
4947
5000
|
this.currentTime = 0;
|
4948
5001
|
this.stallCount = 0;
|
4949
5002
|
this._latency = null;
|
4950
|
-
this.
|
4951
|
-
|
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
|
+
}
|
4952
5040
|
};
|
4953
5041
|
this.hls = hls;
|
4954
5042
|
this.config = hls.config;
|
@@ -4960,7 +5048,7 @@
|
|
4960
5048
|
this.onMediaDetaching();
|
4961
5049
|
this.levelDetails = null;
|
4962
5050
|
// @ts-ignore
|
4963
|
-
this.hls =
|
5051
|
+
this.hls = null;
|
4964
5052
|
};
|
4965
5053
|
_proto.registerListeners = function registerListeners() {
|
4966
5054
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -4978,11 +5066,11 @@
|
|
4978
5066
|
};
|
4979
5067
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
4980
5068
|
this.media = data.media;
|
4981
|
-
this.media.addEventListener('timeupdate', this.
|
5069
|
+
this.media.addEventListener('timeupdate', this.onTimeupdate);
|
4982
5070
|
};
|
4983
5071
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
4984
5072
|
if (this.media) {
|
4985
|
-
this.media.removeEventListener('timeupdate', this.
|
5073
|
+
this.media.removeEventListener('timeupdate', this.onTimeupdate);
|
4986
5074
|
this.media = null;
|
4987
5075
|
}
|
4988
5076
|
};
|
@@ -4995,10 +5083,10 @@
|
|
4995
5083
|
var details = _ref.details;
|
4996
5084
|
this.levelDetails = details;
|
4997
5085
|
if (details.advanced) {
|
4998
|
-
this.
|
5086
|
+
this.onTimeupdate();
|
4999
5087
|
}
|
5000
5088
|
if (!details.live && this.media) {
|
5001
|
-
this.media.removeEventListener('timeupdate', this.
|
5089
|
+
this.media.removeEventListener('timeupdate', this.onTimeupdate);
|
5002
5090
|
}
|
5003
5091
|
};
|
5004
5092
|
_proto.onError = function onError(event, data) {
|
@@ -5008,45 +5096,7 @@
|
|
5008
5096
|
}
|
5009
5097
|
this.stallCount++;
|
5010
5098
|
if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
|
5011
|
-
logger.warn('[
|
5012
|
-
}
|
5013
|
-
};
|
5014
|
-
_proto.timeupdate = function timeupdate() {
|
5015
|
-
var media = this.media,
|
5016
|
-
levelDetails = this.levelDetails;
|
5017
|
-
if (!media || !levelDetails) {
|
5018
|
-
return;
|
5019
|
-
}
|
5020
|
-
this.currentTime = media.currentTime;
|
5021
|
-
var latency = this.computeLatency();
|
5022
|
-
if (latency === null) {
|
5023
|
-
return;
|
5024
|
-
}
|
5025
|
-
this._latency = latency;
|
5026
|
-
|
5027
|
-
// Adapt playbackRate to meet target latency in low-latency mode
|
5028
|
-
var _this$config = this.config,
|
5029
|
-
lowLatencyMode = _this$config.lowLatencyMode,
|
5030
|
-
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5031
|
-
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5032
|
-
return;
|
5033
|
-
}
|
5034
|
-
var targetLatency = this.targetLatency;
|
5035
|
-
if (targetLatency === null) {
|
5036
|
-
return;
|
5037
|
-
}
|
5038
|
-
var distanceFromTarget = latency - targetLatency;
|
5039
|
-
// Only adjust playbackRate when within one target duration of targetLatency
|
5040
|
-
// and more than one second from under-buffering.
|
5041
|
-
// Playback further than one target duration from target can be considered DVR playback.
|
5042
|
-
var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
|
5043
|
-
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5044
|
-
if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
|
5045
|
-
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5046
|
-
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
|
5047
|
-
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5048
|
-
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5049
|
-
media.playbackRate = 1;
|
5099
|
+
this.hls.logger.warn('[latency-controller]: Stall detected, adjusting target latency');
|
5050
5100
|
}
|
5051
5101
|
};
|
5052
5102
|
_proto.estimateLiveEdge = function estimateLiveEdge() {
|
@@ -5954,19 +6004,17 @@
|
|
5954
6004
|
MoveAllAlternatesMatchingHDCP: 2,
|
5955
6005
|
SwitchToSDR: 4
|
5956
6006
|
}; // Reserved for future use
|
5957
|
-
var ErrorController = /*#__PURE__*/function () {
|
6007
|
+
var ErrorController = /*#__PURE__*/function (_Logger) {
|
6008
|
+
_inheritsLoose(ErrorController, _Logger);
|
5958
6009
|
function ErrorController(hls) {
|
5959
|
-
|
5960
|
-
this.
|
5961
|
-
|
5962
|
-
|
5963
|
-
|
5964
|
-
|
5965
|
-
|
5966
|
-
|
5967
|
-
this.warn = logger.warn.bind(logger, "[warning]:");
|
5968
|
-
this.error = logger.error.bind(logger, "[error]:");
|
5969
|
-
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;
|
5970
6018
|
}
|
5971
6019
|
var _proto = ErrorController.prototype;
|
5972
6020
|
_proto.registerListeners = function registerListeners() {
|
@@ -6322,19 +6370,19 @@
|
|
6322
6370
|
}
|
6323
6371
|
};
|
6324
6372
|
return ErrorController;
|
6325
|
-
}();
|
6373
|
+
}(Logger);
|
6326
6374
|
|
6327
|
-
var BasePlaylistController = /*#__PURE__*/function () {
|
6375
|
+
var BasePlaylistController = /*#__PURE__*/function (_Logger) {
|
6376
|
+
_inheritsLoose(BasePlaylistController, _Logger);
|
6328
6377
|
function BasePlaylistController(hls, logPrefix) {
|
6329
|
-
|
6330
|
-
this.
|
6331
|
-
|
6332
|
-
|
6333
|
-
|
6334
|
-
|
6335
|
-
|
6336
|
-
|
6337
|
-
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;
|
6338
6386
|
}
|
6339
6387
|
var _proto = BasePlaylistController.prototype;
|
6340
6388
|
_proto.destroy = function destroy() {
|
@@ -6367,7 +6415,7 @@
|
|
6367
6415
|
try {
|
6368
6416
|
uri = new self.URL(attr.URI, previous.url).href;
|
6369
6417
|
} catch (error) {
|
6370
|
-
|
6418
|
+
this.warn("Could not construct new URL for Rendition Report: " + error);
|
6371
6419
|
uri = attr.URI || '';
|
6372
6420
|
}
|
6373
6421
|
// Use exact match. Otherwise, the last partial match, if any, will be used
|
@@ -6406,7 +6454,7 @@
|
|
6406
6454
|
return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
|
6407
6455
|
};
|
6408
6456
|
_proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
|
6409
|
-
var
|
6457
|
+
var _this2 = this;
|
6410
6458
|
var details = data.details,
|
6411
6459
|
stats = data.stats;
|
6412
6460
|
|
@@ -6511,7 +6559,7 @@
|
|
6511
6559
|
// );
|
6512
6560
|
|
6513
6561
|
this.timer = self.setTimeout(function () {
|
6514
|
-
return
|
6562
|
+
return _this2.loadPlaylist(deliveryDirectives);
|
6515
6563
|
}, estimatedTimeUntilUpdate);
|
6516
6564
|
} else {
|
6517
6565
|
this.clearTimer();
|
@@ -6527,7 +6575,7 @@
|
|
6527
6575
|
return new HlsUrlParameters(msn, part, skip);
|
6528
6576
|
};
|
6529
6577
|
_proto.checkRetry = function checkRetry(errorEvent) {
|
6530
|
-
var
|
6578
|
+
var _this3 = this;
|
6531
6579
|
var errorDetails = errorEvent.details;
|
6532
6580
|
var isTimeout = isTimeoutError(errorEvent);
|
6533
6581
|
var errorAction = errorEvent.errorAction;
|
@@ -6551,7 +6599,7 @@
|
|
6551
6599
|
var delay = getRetryDelay(retryConfig, retryCount);
|
6552
6600
|
// Schedule level/track reload
|
6553
6601
|
this.timer = self.setTimeout(function () {
|
6554
|
-
return
|
6602
|
+
return _this3.loadPlaylist();
|
6555
6603
|
}, delay);
|
6556
6604
|
this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
|
6557
6605
|
}
|
@@ -6562,7 +6610,7 @@
|
|
6562
6610
|
return retry;
|
6563
6611
|
};
|
6564
6612
|
return BasePlaylistController;
|
6565
|
-
}();
|
6613
|
+
}(Logger);
|
6566
6614
|
|
6567
6615
|
/*
|
6568
6616
|
* compute an Exponential Weighted moving average
|
@@ -7164,30 +7212,33 @@
|
|
7164
7212
|
return -1;
|
7165
7213
|
}
|
7166
7214
|
|
7167
|
-
var AbrController = /*#__PURE__*/function () {
|
7215
|
+
var AbrController = /*#__PURE__*/function (_Logger) {
|
7216
|
+
_inheritsLoose(AbrController, _Logger);
|
7168
7217
|
function AbrController(_hls) {
|
7169
|
-
var _this
|
7170
|
-
this.
|
7171
|
-
|
7172
|
-
|
7173
|
-
|
7174
|
-
|
7175
|
-
|
7176
|
-
|
7177
|
-
|
7178
|
-
|
7179
|
-
|
7180
|
-
|
7181
|
-
|
7182
|
-
|
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;
|
7183
7233
|
/*
|
7184
7234
|
This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
|
7185
7235
|
quickly enough to prevent underbuffering
|
7186
7236
|
*/
|
7187
|
-
|
7188
|
-
var
|
7189
|
-
|
7190
|
-
|
7237
|
+
_this._abandonRulesCheck = function () {
|
7238
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
7239
|
+
frag = _assertThisInitialize.fragCurrent,
|
7240
|
+
part = _assertThisInitialize.partCurrent,
|
7241
|
+
hls = _assertThisInitialize.hls;
|
7191
7242
|
var autoLevelEnabled = hls.autoLevelEnabled,
|
7192
7243
|
media = hls.media;
|
7193
7244
|
if (!frag || !media) {
|
@@ -7276,21 +7327,22 @@
|
|
7276
7327
|
_this.resetEstimator(nextLoadLevelBitrate);
|
7277
7328
|
}
|
7278
7329
|
_this.clearTimer();
|
7279
|
-
|
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");
|
7280
7331
|
hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
|
7281
7332
|
frag: frag,
|
7282
7333
|
part: part,
|
7283
7334
|
stats: stats
|
7284
7335
|
});
|
7285
7336
|
};
|
7286
|
-
|
7287
|
-
|
7288
|
-
|
7337
|
+
_this.hls = _hls;
|
7338
|
+
_this.bwEstimator = _this.initEstimator();
|
7339
|
+
_this.registerListeners();
|
7340
|
+
return _this;
|
7289
7341
|
}
|
7290
7342
|
var _proto = AbrController.prototype;
|
7291
7343
|
_proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
|
7292
7344
|
if (abrEwmaDefaultEstimate) {
|
7293
|
-
|
7345
|
+
this.log("setting initial bwe to " + abrEwmaDefaultEstimate);
|
7294
7346
|
this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
|
7295
7347
|
}
|
7296
7348
|
this.firstSelection = -1;
|
@@ -7542,13 +7594,13 @@
|
|
7542
7594
|
// cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
|
7543
7595
|
var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
|
7544
7596
|
maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
|
7545
|
-
|
7597
|
+
this.info("bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
|
7546
7598
|
// don't use conservative factor on bitrate test
|
7547
7599
|
bwFactor = bwUpFactor = 1;
|
7548
7600
|
}
|
7549
7601
|
}
|
7550
7602
|
var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
|
7551
|
-
|
7603
|
+
this.info((bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
|
7552
7604
|
if (bestLevel > -1) {
|
7553
7605
|
return bestLevel;
|
7554
7606
|
}
|
@@ -7604,7 +7656,7 @@
|
|
7604
7656
|
currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
|
7605
7657
|
currentFrameRate = minFramerate;
|
7606
7658
|
currentBw = Math.max(currentBw, minBitrate);
|
7607
|
-
|
7659
|
+
this.log("picked start tier " + JSON.stringify(startTier));
|
7608
7660
|
} else {
|
7609
7661
|
currentCodecSet = level == null ? void 0 : level.codecSet;
|
7610
7662
|
currentVideoRange = level == null ? void 0 : level.videoRange;
|
@@ -7628,11 +7680,11 @@
|
|
7628
7680
|
var levels = _this2.hls.levels;
|
7629
7681
|
var index = levels.indexOf(levelInfo);
|
7630
7682
|
if (decodingInfo.error) {
|
7631
|
-
|
7683
|
+
_this2.warn("MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
|
7632
7684
|
} else if (!decodingInfo.supported) {
|
7633
|
-
|
7685
|
+
_this2.warn("Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
|
7634
7686
|
if (index > -1 && levels.length > 1) {
|
7635
|
-
|
7687
|
+
_this2.log("Removing unsupported level " + index);
|
7636
7688
|
_this2.hls.removeLevel(index);
|
7637
7689
|
}
|
7638
7690
|
}
|
@@ -7679,9 +7731,9 @@
|
|
7679
7731
|
var forcedAutoLevel = _this2.forcedAutoLevel;
|
7680
7732
|
if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
|
7681
7733
|
if (levelsSkipped.length) {
|
7682
|
-
|
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);
|
7683
7735
|
}
|
7684
|
-
|
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);
|
7685
7737
|
}
|
7686
7738
|
if (firstSelection) {
|
7687
7739
|
_this2.firstSelection = i;
|
@@ -7715,7 +7767,7 @@
|
|
7715
7767
|
}
|
7716
7768
|
var firstLevel = this.hls.firstLevel;
|
7717
7769
|
var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
|
7718
|
-
|
7770
|
+
this.warn("Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
|
7719
7771
|
return clamped;
|
7720
7772
|
}
|
7721
7773
|
}, {
|
@@ -7757,15 +7809,18 @@
|
|
7757
7809
|
return nextABRAutoLevel;
|
7758
7810
|
},
|
7759
7811
|
set: function set(nextLevel) {
|
7760
|
-
var
|
7761
|
-
|
7812
|
+
var _this$hls3 = this.hls,
|
7813
|
+
maxAutoLevel = _this$hls3.maxAutoLevel,
|
7814
|
+
minAutoLevel = _this$hls3.minAutoLevel;
|
7815
|
+
var value = Math.min(Math.max(nextLevel, minAutoLevel), maxAutoLevel);
|
7816
|
+
if (this._nextAutoLevel !== value) {
|
7762
7817
|
this.nextAutoLevelKey = '';
|
7763
7818
|
this._nextAutoLevel = value;
|
7764
7819
|
}
|
7765
7820
|
}
|
7766
7821
|
}]);
|
7767
7822
|
return AbrController;
|
7768
|
-
}();
|
7823
|
+
}(Logger);
|
7769
7824
|
|
7770
7825
|
/**
|
7771
7826
|
* @ignore
|
@@ -7796,13 +7851,17 @@
|
|
7796
7851
|
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
|
7797
7852
|
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
|
7798
7853
|
*/
|
7799
|
-
var TaskLoop = /*#__PURE__*/function () {
|
7800
|
-
|
7801
|
-
|
7802
|
-
|
7803
|
-
|
7804
|
-
|
7805
|
-
|
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;
|
7806
7865
|
}
|
7807
7866
|
var _proto = TaskLoop.prototype;
|
7808
7867
|
_proto.destroy = function destroy() {
|
@@ -7888,7 +7947,7 @@
|
|
7888
7947
|
*/;
|
7889
7948
|
_proto.doTick = function doTick() {};
|
7890
7949
|
return TaskLoop;
|
7891
|
-
}();
|
7950
|
+
}(Logger);
|
7892
7951
|
|
7893
7952
|
var FragmentState = {
|
7894
7953
|
NOT_LOADED: "NOT_LOADED",
|
@@ -8907,8 +8966,8 @@
|
|
8907
8966
|
var _frag$decryptdata;
|
8908
8967
|
var byteRangeStart = start;
|
8909
8968
|
var byteRangeEnd = end;
|
8910
|
-
if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method)
|
8911
|
-
// 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,
|
8912
8971
|
// has the unencrypted size specified in the range.
|
8913
8972
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
8914
8973
|
var fragmentLen = end - start;
|
@@ -8941,6 +9000,9 @@
|
|
8941
9000
|
(part ? part : frag).stats.aborted = true;
|
8942
9001
|
return new LoadError(errorData);
|
8943
9002
|
}
|
9003
|
+
function isMethodFullSegmentAesCbc(method) {
|
9004
|
+
return method === 'AES-128' || method === 'AES-256';
|
9005
|
+
}
|
8944
9006
|
var LoadError = /*#__PURE__*/function (_Error) {
|
8945
9007
|
_inheritsLoose(LoadError, _Error);
|
8946
9008
|
function LoadError(data) {
|
@@ -8954,37 +9016,65 @@
|
|
8954
9016
|
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
8955
9017
|
|
8956
9018
|
var AESCrypto = /*#__PURE__*/function () {
|
8957
|
-
function AESCrypto(subtle, iv) {
|
9019
|
+
function AESCrypto(subtle, iv, aesMode) {
|
8958
9020
|
this.subtle = void 0;
|
8959
9021
|
this.aesIV = void 0;
|
9022
|
+
this.aesMode = void 0;
|
8960
9023
|
this.subtle = subtle;
|
8961
9024
|
this.aesIV = iv;
|
9025
|
+
this.aesMode = aesMode;
|
8962
9026
|
}
|
8963
9027
|
var _proto = AESCrypto.prototype;
|
8964
9028
|
_proto.decrypt = function decrypt(data, key) {
|
8965
|
-
|
8966
|
-
|
8967
|
-
|
8968
|
-
|
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
|
+
}
|
8969
9046
|
};
|
8970
9047
|
return AESCrypto;
|
8971
9048
|
}();
|
8972
9049
|
|
8973
9050
|
var FastAESKey = /*#__PURE__*/function () {
|
8974
|
-
function FastAESKey(subtle, key) {
|
9051
|
+
function FastAESKey(subtle, key, aesMode) {
|
8975
9052
|
this.subtle = void 0;
|
8976
9053
|
this.key = void 0;
|
9054
|
+
this.aesMode = void 0;
|
8977
9055
|
this.subtle = subtle;
|
8978
9056
|
this.key = key;
|
9057
|
+
this.aesMode = aesMode;
|
8979
9058
|
}
|
8980
9059
|
var _proto = FastAESKey.prototype;
|
8981
9060
|
_proto.expandKey = function expandKey() {
|
9061
|
+
var subtleAlgoName = getSubtleAlgoName(this.aesMode);
|
8982
9062
|
return this.subtle.importKey('raw', this.key, {
|
8983
|
-
name:
|
9063
|
+
name: subtleAlgoName
|
8984
9064
|
}, false, ['encrypt', 'decrypt']);
|
8985
9065
|
};
|
8986
9066
|
return FastAESKey;
|
8987
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
|
+
}
|
8988
9078
|
|
8989
9079
|
// PKCS7
|
8990
9080
|
function removePadding(array) {
|
@@ -9237,7 +9327,8 @@
|
|
9237
9327
|
this.currentIV = null;
|
9238
9328
|
this.currentResult = null;
|
9239
9329
|
this.useSoftware = void 0;
|
9240
|
-
this.
|
9330
|
+
this.enableSoftwareAES = void 0;
|
9331
|
+
this.enableSoftwareAES = config.enableSoftwareAES;
|
9241
9332
|
this.removePKCS7Padding = removePKCS7Padding;
|
9242
9333
|
// built in decryptor expects PKCS7 padding
|
9243
9334
|
if (removePKCS7Padding) {
|
@@ -9250,9 +9341,7 @@
|
|
9250
9341
|
/* no-op */
|
9251
9342
|
}
|
9252
9343
|
}
|
9253
|
-
|
9254
|
-
this.useSoftware = true;
|
9255
|
-
}
|
9344
|
+
this.useSoftware = this.subtle === null;
|
9256
9345
|
}
|
9257
9346
|
var _proto = Decrypter.prototype;
|
9258
9347
|
_proto.destroy = function destroy() {
|
@@ -9289,11 +9378,11 @@
|
|
9289
9378
|
this.softwareDecrypter = null;
|
9290
9379
|
}
|
9291
9380
|
};
|
9292
|
-
_proto.decrypt = function decrypt(data, key, iv) {
|
9381
|
+
_proto.decrypt = function decrypt(data, key, iv, aesMode) {
|
9293
9382
|
var _this = this;
|
9294
9383
|
if (this.useSoftware) {
|
9295
9384
|
return new Promise(function (resolve, reject) {
|
9296
|
-
_this.softwareDecrypt(new Uint8Array(data), key, iv);
|
9385
|
+
_this.softwareDecrypt(new Uint8Array(data), key, iv, aesMode);
|
9297
9386
|
var decryptResult = _this.flush();
|
9298
9387
|
if (decryptResult) {
|
9299
9388
|
resolve(decryptResult.buffer);
|
@@ -9302,16 +9391,20 @@
|
|
9302
9391
|
}
|
9303
9392
|
});
|
9304
9393
|
}
|
9305
|
-
return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
|
9394
|
+
return this.webCryptoDecrypt(new Uint8Array(data), key, iv, aesMode);
|
9306
9395
|
}
|
9307
9396
|
|
9308
9397
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
9309
9398
|
// data is handled in the flush() call
|
9310
9399
|
;
|
9311
|
-
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
|
9400
|
+
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv, aesMode) {
|
9312
9401
|
var currentIV = this.currentIV,
|
9313
9402
|
currentResult = this.currentResult,
|
9314
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
|
+
}
|
9315
9408
|
this.logOnce('JS AES decrypt');
|
9316
9409
|
// The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
|
9317
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
|
@@ -9344,12 +9437,12 @@
|
|
9344
9437
|
}
|
9345
9438
|
return result;
|
9346
9439
|
};
|
9347
|
-
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
|
9440
|
+
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv, aesMode) {
|
9348
9441
|
var _this2 = this;
|
9349
9442
|
var subtle = this.subtle;
|
9350
9443
|
if (this.key !== key || !this.fastAesKey) {
|
9351
9444
|
this.key = key;
|
9352
|
-
this.fastAesKey = new FastAESKey(subtle, key);
|
9445
|
+
this.fastAesKey = new FastAESKey(subtle, key, aesMode);
|
9353
9446
|
}
|
9354
9447
|
return this.fastAesKey.expandKey().then(function (aesKey) {
|
9355
9448
|
// decrypt using web crypto
|
@@ -9357,22 +9450,25 @@
|
|
9357
9450
|
return Promise.reject(new Error('web crypto not initialized'));
|
9358
9451
|
}
|
9359
9452
|
_this2.logOnce('WebCrypto AES decrypt');
|
9360
|
-
var crypto = new AESCrypto(subtle, new Uint8Array(iv));
|
9453
|
+
var crypto = new AESCrypto(subtle, new Uint8Array(iv), aesMode);
|
9361
9454
|
return crypto.decrypt(data.buffer, aesKey);
|
9362
9455
|
}).catch(function (err) {
|
9363
9456
|
logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
|
9364
|
-
return _this2.onWebCryptoError(data, key, iv);
|
9457
|
+
return _this2.onWebCryptoError(data, key, iv, aesMode);
|
9365
9458
|
});
|
9366
9459
|
};
|
9367
|
-
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
|
9368
|
-
|
9369
|
-
|
9370
|
-
|
9371
|
-
|
9372
|
-
|
9373
|
-
|
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
|
+
}
|
9374
9470
|
}
|
9375
|
-
throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
|
9471
|
+
throw new Error('WebCrypto' + (enableSoftwareAES ? ' and softwareDecrypt' : '') + ': failed to decrypt data');
|
9376
9472
|
};
|
9377
9473
|
_proto.getValidChunk = function getValidChunk(data) {
|
9378
9474
|
var currentChunk = data;
|
@@ -9426,7 +9522,7 @@
|
|
9426
9522
|
_inheritsLoose(BaseStreamController, _TaskLoop);
|
9427
9523
|
function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
|
9428
9524
|
var _this;
|
9429
|
-
_this = _TaskLoop.call(this) || this;
|
9525
|
+
_this = _TaskLoop.call(this, logPrefix, hls.logger) || this;
|
9430
9526
|
_this.hls = void 0;
|
9431
9527
|
_this.fragPrevious = null;
|
9432
9528
|
_this.fragCurrent = null;
|
@@ -9451,25 +9547,87 @@
|
|
9451
9547
|
_this.startFragRequested = false;
|
9452
9548
|
_this.decrypter = void 0;
|
9453
9549
|
_this.initPTS = [];
|
9454
|
-
_this.
|
9455
|
-
_this.
|
9456
|
-
|
9457
|
-
|
9458
|
-
|
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
|
+
};
|
9459
9605
|
_this.playlistType = playlistType;
|
9460
|
-
_this.logPrefix = logPrefix;
|
9461
|
-
_this.log = logger.log.bind(logger, logPrefix + ":");
|
9462
|
-
_this.warn = logger.warn.bind(logger, logPrefix + ":");
|
9463
9606
|
_this.hls = hls;
|
9464
9607
|
_this.fragmentLoader = new FragmentLoader(hls.config);
|
9465
9608
|
_this.keyLoader = keyLoader;
|
9466
9609
|
_this.fragmentTracker = fragmentTracker;
|
9467
9610
|
_this.config = hls.config;
|
9468
9611
|
_this.decrypter = new Decrypter(hls.config);
|
9469
|
-
hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
|
9470
9612
|
return _this;
|
9471
9613
|
}
|
9472
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
|
+
};
|
9473
9631
|
_proto.doTick = function doTick() {
|
9474
9632
|
this.onTickEnd();
|
9475
9633
|
};
|
@@ -9493,6 +9651,12 @@
|
|
9493
9651
|
this.clearNextTick();
|
9494
9652
|
this.state = State.STOPPED;
|
9495
9653
|
};
|
9654
|
+
_proto.pauseBuffering = function pauseBuffering() {
|
9655
|
+
this.buffering = false;
|
9656
|
+
};
|
9657
|
+
_proto.resumeBuffering = function resumeBuffering() {
|
9658
|
+
this.buffering = true;
|
9659
|
+
};
|
9496
9660
|
_proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
|
9497
9661
|
// If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
|
9498
9662
|
// of nothing loading/loaded return false
|
@@ -9523,10 +9687,8 @@
|
|
9523
9687
|
};
|
9524
9688
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
9525
9689
|
var media = this.media = this.mediaBuffer = data.media;
|
9526
|
-
|
9527
|
-
|
9528
|
-
media.addEventListener('seeking', this.onvseeking);
|
9529
|
-
media.addEventListener('ended', this.onvended);
|
9690
|
+
media.addEventListener('seeking', this.onMediaSeeking);
|
9691
|
+
media.addEventListener('ended', this.onMediaEnded);
|
9530
9692
|
var config = this.config;
|
9531
9693
|
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
|
9532
9694
|
this.startLoad(config.startPosition);
|
@@ -9540,10 +9702,9 @@
|
|
9540
9702
|
}
|
9541
9703
|
|
9542
9704
|
// remove video listeners
|
9543
|
-
if (media
|
9544
|
-
media.removeEventListener('seeking', this.
|
9545
|
-
media.removeEventListener('ended', this.
|
9546
|
-
this.onvseeking = this.onvended = null;
|
9705
|
+
if (media) {
|
9706
|
+
media.removeEventListener('seeking', this.onMediaSeeking);
|
9707
|
+
media.removeEventListener('ended', this.onMediaEnded);
|
9547
9708
|
}
|
9548
9709
|
if (this.keyLoader) {
|
9549
9710
|
this.keyLoader.detach();
|
@@ -9553,54 +9714,8 @@
|
|
9553
9714
|
this.fragmentTracker.removeAllFragments();
|
9554
9715
|
this.stopLoad();
|
9555
9716
|
};
|
9556
|
-
_proto.
|
9557
|
-
|
9558
|
-
fragCurrent = this.fragCurrent,
|
9559
|
-
media = this.media,
|
9560
|
-
mediaBuffer = this.mediaBuffer,
|
9561
|
-
state = this.state;
|
9562
|
-
var currentTime = media ? media.currentTime : 0;
|
9563
|
-
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9564
|
-
this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9565
|
-
if (this.state === State.ENDED) {
|
9566
|
-
this.resetLoadingState();
|
9567
|
-
} else if (fragCurrent) {
|
9568
|
-
// Seeking while frag load is in progress
|
9569
|
-
var tolerance = config.maxFragLookUpTolerance;
|
9570
|
-
var fragStartOffset = fragCurrent.start - tolerance;
|
9571
|
-
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9572
|
-
// if seeking out of buffered range or into new one
|
9573
|
-
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9574
|
-
var pastFragment = currentTime > fragEndOffset;
|
9575
|
-
// if the seek position is outside the current fragment range
|
9576
|
-
if (currentTime < fragStartOffset || pastFragment) {
|
9577
|
-
if (pastFragment && fragCurrent.loader) {
|
9578
|
-
this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9579
|
-
fragCurrent.abortRequests();
|
9580
|
-
this.resetLoadingState();
|
9581
|
-
}
|
9582
|
-
this.fragPrevious = null;
|
9583
|
-
}
|
9584
|
-
}
|
9585
|
-
}
|
9586
|
-
if (media) {
|
9587
|
-
// Remove gap fragments
|
9588
|
-
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
9589
|
-
this.lastCurrentTime = currentTime;
|
9590
|
-
}
|
9591
|
-
|
9592
|
-
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9593
|
-
if (!this.loadedmetadata && !bufferInfo.len) {
|
9594
|
-
this.nextLoadPosition = this.startPosition = currentTime;
|
9595
|
-
}
|
9596
|
-
|
9597
|
-
// Async tick to speed up processing
|
9598
|
-
this.tickImmediate();
|
9599
|
-
};
|
9600
|
-
_proto.onMediaEnded = function onMediaEnded() {
|
9601
|
-
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9602
|
-
this.startPosition = this.lastCurrentTime = 0;
|
9603
|
-
};
|
9717
|
+
_proto.onManifestLoading = function onManifestLoading() {};
|
9718
|
+
_proto.onError = function onError(event, data) {};
|
9604
9719
|
_proto.onManifestLoaded = function onManifestLoaded(event, data) {
|
9605
9720
|
this.startTimeOffset = data.startTimeOffset;
|
9606
9721
|
this.initPTS = [];
|
@@ -9610,7 +9725,7 @@
|
|
9610
9725
|
this.stopLoad();
|
9611
9726
|
_TaskLoop.prototype.onHandlerDestroying.call(this);
|
9612
9727
|
// @ts-ignore
|
9613
|
-
this.hls = null;
|
9728
|
+
this.hls = this.onMediaSeeking = this.onMediaEnded = null;
|
9614
9729
|
};
|
9615
9730
|
_proto.onHandlerDestroyed = function onHandlerDestroyed() {
|
9616
9731
|
this.state = State.STOPPED;
|
@@ -9740,10 +9855,10 @@
|
|
9740
9855
|
var decryptData = frag.decryptdata;
|
9741
9856
|
|
9742
9857
|
// check to see if the payload needs to be decrypted
|
9743
|
-
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)) {
|
9744
9859
|
var startTime = self.performance.now();
|
9745
9860
|
// decrypt init segment data
|
9746
|
-
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) {
|
9747
9862
|
hls.trigger(Events.ERROR, {
|
9748
9863
|
type: ErrorTypes.MEDIA_ERROR,
|
9749
9864
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -9856,7 +9971,7 @@
|
|
9856
9971
|
}
|
9857
9972
|
var keyLoadingPromise = null;
|
9858
9973
|
if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
|
9859
|
-
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);
|
9860
9975
|
this.state = State.KEY_LOADING;
|
9861
9976
|
this.fragCurrent = frag;
|
9862
9977
|
keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
|
@@ -9887,7 +10002,7 @@
|
|
9887
10002
|
var partIndex = this.getNextPart(partList, frag, targetBufferTime);
|
9888
10003
|
if (partIndex > -1) {
|
9889
10004
|
var part = partList[partIndex];
|
9890
|
-
this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.
|
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)));
|
9891
10006
|
this.nextLoadPosition = part.start + part.duration;
|
9892
10007
|
this.state = State.FRAG_LOADING;
|
9893
10008
|
var _result;
|
@@ -9920,7 +10035,7 @@
|
|
9920
10035
|
}
|
9921
10036
|
}
|
9922
10037
|
}
|
9923
|
-
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)));
|
9924
10039
|
// Don't update nextLoadPosition for fragments which are not buffered
|
9925
10040
|
if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
|
9926
10041
|
this.nextLoadPosition = frag.start + frag.duration;
|
@@ -10481,7 +10596,7 @@
|
|
10481
10596
|
errorAction.resolved = true;
|
10482
10597
|
}
|
10483
10598
|
} else {
|
10484
|
-
|
10599
|
+
this.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
|
10485
10600
|
return;
|
10486
10601
|
}
|
10487
10602
|
} else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
|
@@ -10881,6 +10996,7 @@
|
|
10881
10996
|
*/
|
10882
10997
|
function getAudioConfig(observer, data, offset, audioCodec) {
|
10883
10998
|
var adtsObjectType;
|
10999
|
+
var originalAdtsObjectType;
|
10884
11000
|
var adtsExtensionSamplingIndex;
|
10885
11001
|
var adtsChannelConfig;
|
10886
11002
|
var config;
|
@@ -10888,7 +11004,7 @@
|
|
10888
11004
|
var manifestCodec = audioCodec;
|
10889
11005
|
var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
|
10890
11006
|
// byte 2
|
10891
|
-
adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
11007
|
+
adtsObjectType = originalAdtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
10892
11008
|
var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
|
10893
11009
|
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
|
10894
11010
|
var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
|
@@ -10905,8 +11021,8 @@
|
|
10905
11021
|
// byte 3
|
10906
11022
|
adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
|
10907
11023
|
logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
|
10908
|
-
//
|
10909
|
-
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)) {
|
10910
11026
|
if (adtsSamplingIndex >= 6) {
|
10911
11027
|
adtsObjectType = 5;
|
10912
11028
|
config = new Array(4);
|
@@ -11000,6 +11116,7 @@
|
|
11000
11116
|
samplerate: adtsSamplingRates[adtsSamplingIndex],
|
11001
11117
|
channelCount: adtsChannelConfig,
|
11002
11118
|
codec: 'mp4a.40.' + adtsObjectType,
|
11119
|
+
parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
|
11003
11120
|
manifestCodec: manifestCodec
|
11004
11121
|
};
|
11005
11122
|
}
|
@@ -11054,7 +11171,8 @@
|
|
11054
11171
|
track.channelCount = config.channelCount;
|
11055
11172
|
track.codec = config.codec;
|
11056
11173
|
track.manifestCodec = config.manifestCodec;
|
11057
|
-
|
11174
|
+
track.parsedCodec = config.parsedCodec;
|
11175
|
+
logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11058
11176
|
}
|
11059
11177
|
}
|
11060
11178
|
function getFrameDuration(samplerate) {
|
@@ -11652,65 +11770,169 @@
|
|
11652
11770
|
logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
|
11653
11771
|
}
|
11654
11772
|
};
|
11655
|
-
|
11656
|
-
|
11657
|
-
|
11658
|
-
|
11659
|
-
|
11660
|
-
|
11661
|
-
|
11662
|
-
|
11663
|
-
|
11664
|
-
|
11665
|
-
|
11666
|
-
|
11667
|
-
this.bitsAvailable = void 0;
|
11668
|
-
this.data = data;
|
11669
|
-
// the number of bytes left to examine in this.data
|
11670
|
-
this.bytesAvailable = data.byteLength;
|
11671
|
-
// the current word being examined
|
11672
|
-
this.word = 0; // :uint
|
11673
|
-
// the number of bits left to examine in the current word
|
11674
|
-
this.bitsAvailable = 0; // :uint
|
11675
|
-
}
|
11676
|
-
|
11677
|
-
// ():void
|
11678
|
-
var _proto = ExpGolomb.prototype;
|
11679
|
-
_proto.loadWord = function loadWord() {
|
11680
|
-
var data = this.data;
|
11681
|
-
var bytesAvailable = this.bytesAvailable;
|
11682
|
-
var position = data.byteLength - bytesAvailable;
|
11683
|
-
var workingBytes = new Uint8Array(4);
|
11684
|
-
var availableBytes = Math.min(4, bytesAvailable);
|
11685
|
-
if (availableBytes === 0) {
|
11686
|
-
throw new Error('no bytes available');
|
11687
|
-
}
|
11688
|
-
workingBytes.set(data.subarray(position, position + availableBytes));
|
11689
|
-
this.word = new DataView(workingBytes.buffer).getUint32(0);
|
11690
|
-
// track the amount of this.data that has been processed
|
11691
|
-
this.bitsAvailable = availableBytes * 8;
|
11692
|
-
this.bytesAvailable -= availableBytes;
|
11693
|
-
}
|
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));
|
11694
11785
|
|
11695
|
-
|
11696
|
-
|
11697
|
-
|
11698
|
-
|
11699
|
-
|
11700
|
-
|
11701
|
-
|
11702
|
-
this.bitsAvailable -= count;
|
11703
|
-
} else {
|
11704
|
-
count -= this.bitsAvailable;
|
11705
|
-
skipBytes = count >> 3;
|
11706
|
-
count -= skipBytes << 3;
|
11707
|
-
this.bytesAvailable -= skipBytes;
|
11708
|
-
this.loadWord();
|
11709
|
-
this.word <<= count;
|
11710
|
-
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;
|
11711
11793
|
}
|
11712
|
-
|
11713
|
-
|
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
|
+
|
11714
11936
|
// (size:int):uint
|
11715
11937
|
;
|
11716
11938
|
_proto.readBits = function readBits(size) {
|
@@ -11806,22 +12028,179 @@
|
|
11806
12028
|
;
|
11807
12029
|
_proto.readUInt = function readUInt() {
|
11808
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();
|
11809
12189
|
}
|
11810
12190
|
|
11811
12191
|
/**
|
11812
|
-
*
|
11813
|
-
* list is optionally transmitted as part of a sequence parameter
|
12192
|
+
* The scaling list is optionally transmitted as part of a sequence parameter
|
11814
12193
|
* set and is not relevant to transmuxing.
|
11815
12194
|
* @param count the number of entries in this scaling list
|
11816
12195
|
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
11817
12196
|
*/;
|
11818
|
-
_proto.skipScalingList = function skipScalingList(count) {
|
12197
|
+
_proto.skipScalingList = function skipScalingList(count, reader) {
|
11819
12198
|
var lastScale = 8;
|
11820
12199
|
var nextScale = 8;
|
11821
12200
|
var deltaScale;
|
11822
12201
|
for (var j = 0; j < count; j++) {
|
11823
12202
|
if (nextScale !== 0) {
|
11824
|
-
deltaScale =
|
12203
|
+
deltaScale = reader.readEG();
|
11825
12204
|
nextScale = (lastScale + deltaScale + 256) % 256;
|
11826
12205
|
}
|
11827
12206
|
lastScale = nextScale === 0 ? lastScale : nextScale;
|
@@ -11836,7 +12215,8 @@
|
|
11836
12215
|
* sequence parameter set, including the dimensions of the
|
11837
12216
|
* associated video frames.
|
11838
12217
|
*/;
|
11839
|
-
_proto.readSPS = function readSPS() {
|
12218
|
+
_proto.readSPS = function readSPS(sps) {
|
12219
|
+
var eg = new ExpGolomb(sps);
|
11840
12220
|
var frameCropLeftOffset = 0;
|
11841
12221
|
var frameCropRightOffset = 0;
|
11842
12222
|
var frameCropTopOffset = 0;
|
@@ -11844,13 +12224,13 @@
|
|
11844
12224
|
var numRefFramesInPicOrderCntCycle;
|
11845
12225
|
var scalingListCount;
|
11846
12226
|
var i;
|
11847
|
-
var readUByte =
|
11848
|
-
var readBits =
|
11849
|
-
var readUEG =
|
11850
|
-
var readBoolean =
|
11851
|
-
var skipBits =
|
11852
|
-
var skipEG =
|
11853
|
-
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);
|
11854
12234
|
var skipScalingList = this.skipScalingList.bind(this);
|
11855
12235
|
readUByte();
|
11856
12236
|
var profileIdc = readUByte(); // profile_idc
|
@@ -11875,9 +12255,9 @@
|
|
11875
12255
|
if (readBoolean()) {
|
11876
12256
|
// seq_scaling_list_present_flag[ i ]
|
11877
12257
|
if (i < 6) {
|
11878
|
-
skipScalingList(16);
|
12258
|
+
skipScalingList(16, eg);
|
11879
12259
|
} else {
|
11880
|
-
skipScalingList(64);
|
12260
|
+
skipScalingList(64, eg);
|
11881
12261
|
}
|
11882
12262
|
}
|
11883
12263
|
}
|
@@ -11982,26 +12362,24 @@
|
|
11982
12362
|
pixelRatio: pixelRatio
|
11983
12363
|
};
|
11984
12364
|
};
|
11985
|
-
|
11986
|
-
|
11987
|
-
this.readUByte();
|
11988
|
-
// discard first_mb_in_slice
|
11989
|
-
this.readUEG();
|
11990
|
-
// return slice_type
|
11991
|
-
return this.readUEG();
|
11992
|
-
};
|
11993
|
-
return ExpGolomb;
|
11994
|
-
}();
|
12365
|
+
return AvcVideoParser;
|
12366
|
+
}(BaseVideoParser);
|
11995
12367
|
|
11996
|
-
var
|
11997
|
-
_inheritsLoose(
|
11998
|
-
function
|
11999
|
-
|
12000
|
-
|
12001
|
-
|
12002
|
-
|
12003
|
-
|
12004
|
-
|
12368
|
+
var HevcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
|
12369
|
+
_inheritsLoose(HevcVideoParser, _BaseVideoParser);
|
12370
|
+
function HevcVideoParser() {
|
12371
|
+
var _this;
|
12372
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
12373
|
+
args[_key] = arguments[_key];
|
12374
|
+
}
|
12375
|
+
_this = _BaseVideoParser.call.apply(_BaseVideoParser, [this].concat(args)) || this;
|
12376
|
+
_this.initVPS = null;
|
12377
|
+
return _this;
|
12378
|
+
}
|
12379
|
+
var _proto = HevcVideoParser.prototype;
|
12380
|
+
_proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
|
12381
|
+
var _this2 = this;
|
12382
|
+
var units = this.parseNALu(track, pes.data);
|
12005
12383
|
var VideoSample = this.VideoSample;
|
12006
12384
|
var push;
|
12007
12385
|
var spsfound = false;
|
@@ -12017,112 +12395,143 @@
|
|
12017
12395
|
units.forEach(function (unit) {
|
12018
12396
|
var _VideoSample2;
|
12019
12397
|
switch (unit.type) {
|
12020
|
-
//
|
12398
|
+
// NON-IDR, NON RANDOM ACCESS SLICE
|
12399
|
+
case 0:
|
12021
12400
|
case 1:
|
12022
|
-
|
12023
|
-
|
12024
|
-
|
12025
|
-
|
12026
|
-
|
12027
|
-
|
12028
|
-
|
12029
|
-
|
12030
|
-
|
12031
|
-
|
12032
|
-
|
12033
|
-
|
12034
|
-
|
12035
|
-
|
12036
|
-
|
12037
|
-
|
12038
|
-
|
12039
|
-
|
12040
|
-
|
12041
|
-
|
12042
|
-
|
12043
|
-
|
12044
|
-
|
12045
|
-
|
12046
|
-
|
12047
|
-
if (!VideoSample) {
|
12048
|
-
|
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;
|
12049
12429
|
}
|
12050
|
-
VideoSample.frame = true;
|
12051
|
-
VideoSample.key = iskey;
|
12052
|
-
break;
|
12053
|
-
// IDR
|
12054
12430
|
}
|
12055
|
-
|
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:
|
12056
12441
|
push = true;
|
12057
12442
|
// handle PES not starting with AUD
|
12058
12443
|
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12059
12444
|
if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
|
12060
|
-
|
12061
|
-
VideoSample =
|
12445
|
+
_this2.pushAccessUnit(VideoSample, track);
|
12446
|
+
VideoSample = _this2.VideoSample = null;
|
12062
12447
|
}
|
12063
12448
|
if (!VideoSample) {
|
12064
|
-
VideoSample =
|
12449
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12065
12450
|
}
|
12066
12451
|
VideoSample.key = true;
|
12067
12452
|
VideoSample.frame = true;
|
12068
12453
|
break;
|
12454
|
+
|
12069
12455
|
// SEI
|
12070
|
-
case
|
12071
|
-
|
12072
|
-
|
12073
|
-
|
12074
|
-
|
12075
|
-
|
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;
|
12076
12470
|
}
|
12077
|
-
|
12078
|
-
|
12079
|
-
|
12080
|
-
|
12081
|
-
|
12082
|
-
|
12083
|
-
|
12084
|
-
|
12085
|
-
if (
|
12086
|
-
|
12087
|
-
track.
|
12088
|
-
|
12089
|
-
|
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;
|
12090
12488
|
track.duration = duration;
|
12091
|
-
|
12092
|
-
|
12093
|
-
for (var
|
12094
|
-
|
12095
|
-
if (h.length < 2) {
|
12096
|
-
h = '0' + h;
|
12097
|
-
}
|
12098
|
-
codecstring += h;
|
12489
|
+
track.codec = _config.codecString;
|
12490
|
+
track.sps = [];
|
12491
|
+
for (var prop in _config.params) {
|
12492
|
+
track.params[prop] = _config.params[prop];
|
12099
12493
|
}
|
12100
|
-
track.codec = codecstring;
|
12101
12494
|
}
|
12102
|
-
|
12495
|
+
if (track.vps !== undefined && track.vps[0] === _this2.initVPS) {
|
12496
|
+
track.sps.push(unit.data);
|
12497
|
+
}
|
12103
12498
|
}
|
12499
|
+
if (!VideoSample) {
|
12500
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12501
|
+
}
|
12502
|
+
VideoSample.key = true;
|
12503
|
+
break;
|
12504
|
+
|
12104
12505
|
// PPS
|
12105
|
-
case
|
12506
|
+
case 34:
|
12106
12507
|
push = true;
|
12107
|
-
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
|
+
}
|
12108
12520
|
break;
|
12109
|
-
|
12110
|
-
|
12521
|
+
|
12522
|
+
// ACCESS UNIT DELIMITER
|
12523
|
+
case 35:
|
12111
12524
|
push = true;
|
12112
12525
|
track.audFound = true;
|
12113
12526
|
if (VideoSample) {
|
12114
|
-
|
12527
|
+
_this2.pushAccessUnit(VideoSample, track);
|
12115
12528
|
}
|
12116
|
-
VideoSample =
|
12117
|
-
break;
|
12118
|
-
// Filler Data
|
12119
|
-
case 12:
|
12120
|
-
push = true;
|
12529
|
+
VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
|
12121
12530
|
break;
|
12122
12531
|
default:
|
12123
12532
|
push = false;
|
12124
12533
|
if (VideoSample) {
|
12125
|
-
VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
|
12534
|
+
VideoSample.debug += 'unknown or irrelevant NAL ' + unit.type + ' ';
|
12126
12535
|
}
|
12127
12536
|
break;
|
12128
12537
|
}
|
@@ -12137,111 +12546,425 @@
|
|
12137
12546
|
this.VideoSample = null;
|
12138
12547
|
}
|
12139
12548
|
};
|
12140
|
-
_proto.
|
12141
|
-
|
12142
|
-
|
12143
|
-
|
12144
|
-
var
|
12145
|
-
var
|
12146
|
-
var
|
12147
|
-
|
12148
|
-
|
12149
|
-
|
12150
|
-
|
12151
|
-
|
12152
|
-
|
12153
|
-
if (state === -1) {
|
12154
|
-
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
12155
|
-
lastUnitStart = 0;
|
12156
|
-
// NALu type is value read from offset 0
|
12157
|
-
lastUnitType = array[0] & 0x1f;
|
12158
|
-
state = 0;
|
12159
|
-
i = 1;
|
12160
|
-
}
|
12161
|
-
while (i < len) {
|
12162
|
-
value = array[i++];
|
12163
|
-
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
12164
|
-
if (!state) {
|
12165
|
-
state = value ? 0 : 1;
|
12166
|
-
continue;
|
12167
|
-
}
|
12168
|
-
if (state === 1) {
|
12169
|
-
state = value ? 0 : 2;
|
12170
|
-
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
|
+
}
|
12171
12561
|
}
|
12172
|
-
|
12173
|
-
|
12174
|
-
|
12175
|
-
|
12176
|
-
|
12177
|
-
|
12178
|
-
|
12179
|
-
|
12180
|
-
|
12181
|
-
|
12182
|
-
|
12183
|
-
|
12184
|
-
|
12185
|
-
|
12186
|
-
|
12187
|
-
|
12188
|
-
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
12189
|
-
var lastUnit = this.getLastNalUnit(track.samples);
|
12190
|
-
if (lastUnit) {
|
12191
|
-
if (lastState && i <= 4 - lastState) {
|
12192
|
-
// start delimiter overlapping between PES packets
|
12193
|
-
// strip start delimiter bytes from the end of last NAL unit
|
12194
|
-
// check if lastUnit had a state different from zero
|
12195
|
-
if (lastUnit.state) {
|
12196
|
-
// strip last bytes
|
12197
|
-
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
|
12198
|
-
}
|
12199
|
-
}
|
12200
|
-
// 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
|
12201
12578
|
|
12202
|
-
|
12203
|
-
|
12204
|
-
|
12205
|
-
|
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
|
+
}
|
12206
12686
|
}
|
12207
12687
|
}
|
12208
12688
|
}
|
12209
|
-
// check if we can read unit type
|
12210
|
-
if (i < len) {
|
12211
|
-
unitType = array[i] & 0x1f;
|
12212
|
-
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
12213
|
-
lastUnitStart = i;
|
12214
|
-
lastUnitType = unitType;
|
12215
|
-
state = 0;
|
12216
|
-
} else {
|
12217
|
-
// not enough byte to read unit type. let's read it on next PES parsing
|
12218
|
-
state = -1;
|
12219
|
-
}
|
12220
|
-
} else {
|
12221
|
-
state = 0;
|
12222
12689
|
}
|
12223
12690
|
}
|
12224
|
-
|
12225
|
-
|
12226
|
-
|
12227
|
-
|
12228
|
-
|
12229
|
-
|
12230
|
-
|
12231
|
-
|
12232
|
-
}
|
12233
|
-
|
12234
|
-
|
12235
|
-
|
12236
|
-
var
|
12237
|
-
if (
|
12238
|
-
|
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
|
+
}
|
12239
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
|
12240
12958
|
}
|
12241
|
-
|
12242
|
-
|
12959
|
+
return {
|
12960
|
+
parallelismType: parallelismType
|
12961
|
+
};
|
12243
12962
|
};
|
12244
|
-
|
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;
|
12245
12968
|
}(BaseVideoParser);
|
12246
12969
|
|
12247
12970
|
/**
|
@@ -12259,7 +12982,7 @@
|
|
12259
12982
|
}
|
12260
12983
|
var _proto = SampleAesDecrypter.prototype;
|
12261
12984
|
_proto.decryptBuffer = function decryptBuffer(encryptedData) {
|
12262
|
-
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);
|
12263
12986
|
}
|
12264
12987
|
|
12265
12988
|
// AAC - encrypt all full 16 bytes blocks starting from offset 16
|
@@ -12378,7 +13101,7 @@
|
|
12378
13101
|
this.observer = observer;
|
12379
13102
|
this.config = config;
|
12380
13103
|
this.typeSupported = typeSupported;
|
12381
|
-
this.videoParser =
|
13104
|
+
this.videoParser = null;
|
12382
13105
|
}
|
12383
13106
|
TSDemuxer.probe = function probe(data) {
|
12384
13107
|
var syncOffset = TSDemuxer.syncOffset(data);
|
@@ -12548,7 +13271,19 @@
|
|
12548
13271
|
case videoPid:
|
12549
13272
|
if (stt) {
|
12550
13273
|
if (videoData && (pes = parsePES(videoData))) {
|
12551
|
-
this.videoParser
|
13274
|
+
if (this.videoParser === null) {
|
13275
|
+
switch (videoTrack.segmentCodec) {
|
13276
|
+
case 'avc':
|
13277
|
+
this.videoParser = new AvcVideoParser();
|
13278
|
+
break;
|
13279
|
+
case 'hevc':
|
13280
|
+
this.videoParser = new HevcVideoParser();
|
13281
|
+
break;
|
13282
|
+
}
|
13283
|
+
}
|
13284
|
+
if (this.videoParser !== null) {
|
13285
|
+
this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
|
13286
|
+
}
|
12552
13287
|
}
|
12553
13288
|
videoData = {
|
12554
13289
|
data: [],
|
@@ -12711,8 +13446,20 @@
|
|
12711
13446
|
// try to parse last PES packets
|
12712
13447
|
var pes;
|
12713
13448
|
if (videoData && (pes = parsePES(videoData))) {
|
12714
|
-
this.videoParser
|
12715
|
-
|
13449
|
+
if (this.videoParser === null) {
|
13450
|
+
switch (videoTrack.segmentCodec) {
|
13451
|
+
case 'avc':
|
13452
|
+
this.videoParser = new AvcVideoParser();
|
13453
|
+
break;
|
13454
|
+
case 'hevc':
|
13455
|
+
this.videoParser = new HevcVideoParser();
|
13456
|
+
break;
|
13457
|
+
}
|
13458
|
+
}
|
13459
|
+
if (this.videoParser !== null) {
|
13460
|
+
this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
|
13461
|
+
videoTrack.pesData = null;
|
13462
|
+
}
|
12716
13463
|
} else {
|
12717
13464
|
// either avcData null or PES truncated, keep it for next frag parsing
|
12718
13465
|
videoTrack.pesData = videoData;
|
@@ -13044,7 +13791,12 @@
|
|
13044
13791
|
logger.warn('Unsupported EC-3 in M2TS found');
|
13045
13792
|
break;
|
13046
13793
|
case 0x24:
|
13047
|
-
|
13794
|
+
// ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
|
13795
|
+
if (result.videoPid === -1) {
|
13796
|
+
result.videoPid = pid;
|
13797
|
+
result.segmentVideoCodec = 'hevc';
|
13798
|
+
logger.log('HEVC in M2TS found');
|
13799
|
+
}
|
13048
13800
|
break;
|
13049
13801
|
}
|
13050
13802
|
// move to the next table entry
|
@@ -13272,6 +14024,8 @@
|
|
13272
14024
|
avc1: [],
|
13273
14025
|
// codingname
|
13274
14026
|
avcC: [],
|
14027
|
+
hvc1: [],
|
14028
|
+
hvcC: [],
|
13275
14029
|
btrt: [],
|
13276
14030
|
dinf: [],
|
13277
14031
|
dref: [],
|
@@ -13699,8 +14453,10 @@
|
|
13699
14453
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
13700
14454
|
}
|
13701
14455
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
13702
|
-
} else {
|
14456
|
+
} else if (track.segmentCodec === 'avc') {
|
13703
14457
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
14458
|
+
} else {
|
14459
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.hvc1(track));
|
13704
14460
|
}
|
13705
14461
|
};
|
13706
14462
|
MP4.tkhd = function tkhd(track) {
|
@@ -13838,6 +14594,84 @@
|
|
13838
14594
|
var result = appendUint8Array(MP4.FTYP, movie);
|
13839
14595
|
return result;
|
13840
14596
|
};
|
14597
|
+
MP4.hvc1 = function hvc1(track) {
|
14598
|
+
var ps = track.params;
|
14599
|
+
var units = [track.vps, track.sps, track.pps];
|
14600
|
+
var NALuLengthSize = 4;
|
14601
|
+
var config = new Uint8Array([0x01, ps.general_profile_space << 6 | (ps.general_tier_flag ? 32 : 0) | ps.general_profile_idc, ps.general_profile_compatibility_flags[0], ps.general_profile_compatibility_flags[1], ps.general_profile_compatibility_flags[2], ps.general_profile_compatibility_flags[3], ps.general_constraint_indicator_flags[0], ps.general_constraint_indicator_flags[1], ps.general_constraint_indicator_flags[2], ps.general_constraint_indicator_flags[3], ps.general_constraint_indicator_flags[4], ps.general_constraint_indicator_flags[5], ps.general_level_idc, 240 | ps.min_spatial_segmentation_idc >> 8, 255 & ps.min_spatial_segmentation_idc, 252 | ps.parallelismType, 252 | ps.chroma_format_idc, 248 | ps.bit_depth_luma_minus8, 248 | ps.bit_depth_chroma_minus8, 0x00, parseInt(ps.frame_rate.fps), NALuLengthSize - 1 | ps.temporal_id_nested << 2 | ps.num_temporal_layers << 3 | (ps.frame_rate.fixed ? 64 : 0), units.length]);
|
14602
|
+
|
14603
|
+
// compute hvcC size in bytes
|
14604
|
+
var length = config.length;
|
14605
|
+
for (var i = 0; i < units.length; i += 1) {
|
14606
|
+
length += 3;
|
14607
|
+
for (var j = 0; j < units[i].length; j += 1) {
|
14608
|
+
length += 2 + units[i][j].length;
|
14609
|
+
}
|
14610
|
+
}
|
14611
|
+
var hvcC = new Uint8Array(length);
|
14612
|
+
hvcC.set(config, 0);
|
14613
|
+
length = config.length;
|
14614
|
+
// append parameter set units: one vps, one or more sps and pps
|
14615
|
+
var iMax = units.length - 1;
|
14616
|
+
for (var _i = 0; _i < units.length; _i += 1) {
|
14617
|
+
hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
|
14618
|
+
length += 3;
|
14619
|
+
for (var _j = 0; _j < units[_i].length; _j += 1) {
|
14620
|
+
hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
|
14621
|
+
length += 2;
|
14622
|
+
hvcC.set(units[_i][_j], length);
|
14623
|
+
length += units[_i][_j].length;
|
14624
|
+
}
|
14625
|
+
}
|
14626
|
+
var hvcc = MP4.box(MP4.types.hvcC, hvcC);
|
14627
|
+
var width = track.width;
|
14628
|
+
var height = track.height;
|
14629
|
+
var hSpacing = track.pixelRatio[0];
|
14630
|
+
var vSpacing = track.pixelRatio[1];
|
14631
|
+
return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
|
14632
|
+
// reserved
|
14633
|
+
0x00, 0x00, 0x00,
|
14634
|
+
// reserved
|
14635
|
+
0x00, 0x01,
|
14636
|
+
// data_reference_index
|
14637
|
+
0x00, 0x00,
|
14638
|
+
// pre_defined
|
14639
|
+
0x00, 0x00,
|
14640
|
+
// reserved
|
14641
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
14642
|
+
// pre_defined
|
14643
|
+
width >> 8 & 0xff, width & 0xff,
|
14644
|
+
// width
|
14645
|
+
height >> 8 & 0xff, height & 0xff,
|
14646
|
+
// height
|
14647
|
+
0x00, 0x48, 0x00, 0x00,
|
14648
|
+
// horizresolution
|
14649
|
+
0x00, 0x48, 0x00, 0x00,
|
14650
|
+
// vertresolution
|
14651
|
+
0x00, 0x00, 0x00, 0x00,
|
14652
|
+
// reserved
|
14653
|
+
0x00, 0x01,
|
14654
|
+
// frame_count
|
14655
|
+
0x12, 0x64, 0x61, 0x69, 0x6c,
|
14656
|
+
// dailymotion/hls.js
|
14657
|
+
0x79, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x6c, 0x73, 0x2e, 0x6a, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
14658
|
+
// compressorname
|
14659
|
+
0x00, 0x18,
|
14660
|
+
// depth = 24
|
14661
|
+
0x11, 0x11]),
|
14662
|
+
// pre_defined = -1
|
14663
|
+
hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
|
14664
|
+
// bufferSizeDB
|
14665
|
+
0x00, 0x2d, 0xc6, 0xc0,
|
14666
|
+
// maxBitrate
|
14667
|
+
0x00, 0x2d, 0xc6, 0xc0])),
|
14668
|
+
// avgBitrate
|
14669
|
+
MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
|
14670
|
+
// hSpacing
|
14671
|
+
hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
|
14672
|
+
// vSpacing
|
14673
|
+
vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
|
14674
|
+
};
|
13841
14675
|
return MP4;
|
13842
14676
|
}();
|
13843
14677
|
MP4.types = void 0;
|
@@ -14239,9 +15073,9 @@
|
|
14239
15073
|
var foundOverlap = delta < -1;
|
14240
15074
|
if (foundHole || foundOverlap) {
|
14241
15075
|
if (foundHole) {
|
14242
|
-
logger.warn("
|
15076
|
+
logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
|
14243
15077
|
} else {
|
14244
|
-
logger.warn("
|
15078
|
+
logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
|
14245
15079
|
}
|
14246
15080
|
if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
|
14247
15081
|
firstDTS = nextAvcDts;
|
@@ -14250,12 +15084,24 @@
|
|
14250
15084
|
inputSamples[0].dts = firstDTS;
|
14251
15085
|
inputSamples[0].pts = firstPTS;
|
14252
15086
|
} else {
|
15087
|
+
var isPTSOrderRetained = true;
|
14253
15088
|
for (var _i = 0; _i < inputSamples.length; _i++) {
|
14254
|
-
if (inputSamples[_i].dts > firstPTS) {
|
15089
|
+
if (inputSamples[_i].dts > firstPTS && isPTSOrderRetained) {
|
14255
15090
|
break;
|
14256
15091
|
}
|
15092
|
+
var prevPTS = inputSamples[_i].pts;
|
14257
15093
|
inputSamples[_i].dts -= delta;
|
14258
15094
|
inputSamples[_i].pts -= delta;
|
15095
|
+
|
15096
|
+
// check to see if this sample's PTS order has changed
|
15097
|
+
// relative to the next one
|
15098
|
+
if (_i < inputSamples.length - 1) {
|
15099
|
+
var nextSamplePTS = inputSamples[_i + 1].pts;
|
15100
|
+
var currentSamplePTS = inputSamples[_i].pts;
|
15101
|
+
var currentOrder = nextSamplePTS <= currentSamplePTS;
|
15102
|
+
var prevOrder = nextSamplePTS <= prevPTS;
|
15103
|
+
isPTSOrderRetained = currentOrder == prevOrder;
|
15104
|
+
}
|
14259
15105
|
}
|
14260
15106
|
}
|
14261
15107
|
logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
|
@@ -14403,7 +15249,7 @@
|
|
14403
15249
|
}
|
14404
15250
|
}
|
14405
15251
|
}
|
14406
|
-
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
15252
|
+
// next AVC/HEVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
14407
15253
|
mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
|
14408
15254
|
this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
|
14409
15255
|
this.videoSampleDuration = mp4SampleDuration;
|
@@ -14538,7 +15384,7 @@
|
|
14538
15384
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
14539
15385
|
for (var j = 0; j < missing; j++) {
|
14540
15386
|
var newStamp = Math.max(nextPts, 0);
|
14541
|
-
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15387
|
+
var fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
|
14542
15388
|
if (!fillFrame) {
|
14543
15389
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
14544
15390
|
fillFrame = sample.unit.subarray();
|
@@ -14666,7 +15512,7 @@
|
|
14666
15512
|
// samples count of this segment's duration
|
14667
15513
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
14668
15514
|
// silent frame
|
14669
|
-
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15515
|
+
var silentFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
|
14670
15516
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
14671
15517
|
// Can't remux if we can't generate a silent frame...
|
14672
15518
|
if (!silentFrame) {
|
@@ -15056,13 +15902,15 @@
|
|
15056
15902
|
duration = transmuxConfig.duration,
|
15057
15903
|
initSegmentData = transmuxConfig.initSegmentData;
|
15058
15904
|
var keyData = getEncryptionType(uintData, decryptdata);
|
15059
|
-
if (keyData && keyData.method
|
15905
|
+
if (keyData && isFullSegmentEncryption(keyData.method)) {
|
15060
15906
|
var decrypter = this.getDecrypter();
|
15907
|
+
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
15908
|
+
|
15061
15909
|
// Software decryption is synchronous; webCrypto is not
|
15062
15910
|
if (decrypter.isSync()) {
|
15063
15911
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
15064
15912
|
// data is handled in the flush() call
|
15065
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
15913
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode);
|
15066
15914
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
15067
15915
|
var loadingParts = chunkMeta.part > -1;
|
15068
15916
|
if (loadingParts) {
|
@@ -15074,7 +15922,7 @@
|
|
15074
15922
|
}
|
15075
15923
|
uintData = new Uint8Array(decryptedData);
|
15076
15924
|
} else {
|
15077
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
15925
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(function (decryptedData) {
|
15078
15926
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
15079
15927
|
// the decrypted data has been transmuxed
|
15080
15928
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -15695,7 +16543,7 @@
|
|
15695
16543
|
observer.on(Events.ERROR, forwardMessage);
|
15696
16544
|
|
15697
16545
|
// forward logger events to main thread
|
15698
|
-
var forwardWorkerLogs = function forwardWorkerLogs() {
|
16546
|
+
var forwardWorkerLogs = function forwardWorkerLogs(logger) {
|
15699
16547
|
var _loop = function _loop(logFn) {
|
15700
16548
|
var func = function func(message) {
|
15701
16549
|
forwardMessage('workerLog', {
|
@@ -15716,8 +16564,8 @@
|
|
15716
16564
|
{
|
15717
16565
|
var config = JSON.parse(data.config);
|
15718
16566
|
self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
|
15719
|
-
enableLogs(config.debug, data.id);
|
15720
|
-
forwardWorkerLogs();
|
16567
|
+
var logger = enableLogs(config.debug, data.id);
|
16568
|
+
forwardWorkerLogs(logger);
|
15721
16569
|
forwardMessage('init', null);
|
15722
16570
|
break;
|
15723
16571
|
}
|
@@ -15891,16 +16739,7 @@
|
|
15891
16739
|
this.observer = new EventEmitter();
|
15892
16740
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
15893
16741
|
this.observer.on(Events.ERROR, forwardMessage);
|
15894
|
-
var
|
15895
|
-
isTypeSupported: function isTypeSupported() {
|
15896
|
-
return false;
|
15897
|
-
}
|
15898
|
-
};
|
15899
|
-
var m2tsTypeSupported = {
|
15900
|
-
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
15901
|
-
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
15902
|
-
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
15903
|
-
};
|
16742
|
+
var m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
|
15904
16743
|
|
15905
16744
|
// navigator.vendor is not always available in Web Worker
|
15906
16745
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -16184,7 +17023,7 @@
|
|
16184
17023
|
_inheritsLoose(AudioStreamController, _BaseStreamController);
|
16185
17024
|
function AudioStreamController(hls, fragmentTracker, keyLoader) {
|
16186
17025
|
var _this;
|
16187
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
17026
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
|
16188
17027
|
_this.videoBuffer = null;
|
16189
17028
|
_this.videoTrackCC = -1;
|
16190
17029
|
_this.waitingVideoCC = -1;
|
@@ -16196,27 +17035,24 @@
|
|
16196
17035
|
_this.flushing = false;
|
16197
17036
|
_this.bufferFlushed = false;
|
16198
17037
|
_this.cachedTrackLoadedData = null;
|
16199
|
-
_this.
|
17038
|
+
_this.registerListeners();
|
16200
17039
|
return _this;
|
16201
17040
|
}
|
16202
17041
|
var _proto = AudioStreamController.prototype;
|
16203
17042
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
16204
|
-
this.
|
17043
|
+
this.unregisterListeners();
|
16205
17044
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
16206
17045
|
this.mainDetails = null;
|
16207
17046
|
this.bufferedTrack = null;
|
16208
17047
|
this.switchingTrack = null;
|
16209
17048
|
};
|
16210
|
-
_proto.
|
17049
|
+
_proto.registerListeners = function registerListeners() {
|
17050
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
16211
17051
|
var hls = this.hls;
|
16212
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16213
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16214
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
16215
17052
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16216
17053
|
hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16217
17054
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16218
17055
|
hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16219
|
-
hls.on(Events.ERROR, this.onError, this);
|
16220
17056
|
hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
|
16221
17057
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16222
17058
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -16224,16 +17060,16 @@
|
|
16224
17060
|
hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
|
16225
17061
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
16226
17062
|
};
|
16227
|
-
_proto.
|
17063
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
16228
17064
|
var hls = this.hls;
|
16229
|
-
hls
|
16230
|
-
|
16231
|
-
|
17065
|
+
if (!hls) {
|
17066
|
+
return;
|
17067
|
+
}
|
17068
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
16232
17069
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
16233
17070
|
hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
16234
17071
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
16235
17072
|
hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16236
|
-
hls.off(Events.ERROR, this.onError, this);
|
16237
17073
|
hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
|
16238
17074
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
16239
17075
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -16392,12 +17228,13 @@
|
|
16392
17228
|
trackId = this.trackId;
|
16393
17229
|
var config = hls.config;
|
16394
17230
|
|
16395
|
-
// 1. if
|
17231
|
+
// 1. if buffering is suspended
|
17232
|
+
// 2. if video not attached AND
|
16396
17233
|
// start fragment already requested OR start frag prefetch not enabled
|
16397
|
-
//
|
17234
|
+
// 3. if tracks or track not loaded and selected
|
16398
17235
|
// then exit loop
|
16399
17236
|
// => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
|
16400
|
-
if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
17237
|
+
if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
16401
17238
|
return;
|
16402
17239
|
}
|
16403
17240
|
var levelInfo = levels[trackId];
|
@@ -16583,7 +17420,7 @@
|
|
16583
17420
|
|
16584
17421
|
// compute start position if we are aligned with the main playlist
|
16585
17422
|
if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {
|
16586
|
-
this.setStartPosition(
|
17423
|
+
this.setStartPosition(this.mainDetails || newDetails, sliding);
|
16587
17424
|
}
|
16588
17425
|
// only switch back to IDLE state if we were waiting for track to start downloading a new fragment
|
16589
17426
|
if (this.state === State.WAITING_TRACK && !this.waitForCdnTuneIn(newDetails)) {
|
@@ -16926,7 +17763,7 @@
|
|
16926
17763
|
_inheritsLoose(AudioTrackController, _BasePlaylistControll);
|
16927
17764
|
function AudioTrackController(hls) {
|
16928
17765
|
var _this;
|
16929
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
17766
|
+
_this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
|
16930
17767
|
_this.tracks = [];
|
16931
17768
|
_this.groupIds = null;
|
16932
17769
|
_this.tracksInGroup = [];
|
@@ -17255,26 +18092,23 @@
|
|
17255
18092
|
_inheritsLoose(SubtitleStreamController, _BaseStreamController);
|
17256
18093
|
function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
|
17257
18094
|
var _this;
|
17258
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
18095
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
|
17259
18096
|
_this.currentTrackId = -1;
|
17260
18097
|
_this.tracksBuffered = [];
|
17261
18098
|
_this.mainDetails = null;
|
17262
|
-
_this.
|
18099
|
+
_this.registerListeners();
|
17263
18100
|
return _this;
|
17264
18101
|
}
|
17265
18102
|
var _proto = SubtitleStreamController.prototype;
|
17266
18103
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
17267
|
-
this.
|
18104
|
+
this.unregisterListeners();
|
17268
18105
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
17269
18106
|
this.mainDetails = null;
|
17270
18107
|
};
|
17271
|
-
_proto.
|
18108
|
+
_proto.registerListeners = function registerListeners() {
|
18109
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
17272
18110
|
var hls = this.hls;
|
17273
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17274
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17275
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17276
18111
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17277
|
-
hls.on(Events.ERROR, this.onError, this);
|
17278
18112
|
hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17279
18113
|
hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17280
18114
|
hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17282,13 +18116,10 @@
|
|
17282
18116
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
17283
18117
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
17284
18118
|
};
|
17285
|
-
_proto.
|
18119
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
18120
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
17286
18121
|
var hls = this.hls;
|
17287
|
-
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17288
|
-
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17289
|
-
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17290
18122
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17291
|
-
hls.off(Events.ERROR, this.onError, this);
|
17292
18123
|
hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
17293
18124
|
hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
17294
18125
|
hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -17486,7 +18317,7 @@
|
|
17486
18317
|
track.details = newDetails;
|
17487
18318
|
this.levelLastLoaded = track;
|
17488
18319
|
if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {
|
17489
|
-
this.setStartPosition(
|
18320
|
+
this.setStartPosition(this.mainDetails || newDetails, sliding);
|
17490
18321
|
}
|
17491
18322
|
|
17492
18323
|
// trigger handler right now
|
@@ -17511,10 +18342,10 @@
|
|
17511
18342
|
return;
|
17512
18343
|
}
|
17513
18344
|
// check to see if the payload needs to be decrypted
|
17514
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method
|
18345
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
|
17515
18346
|
var startTime = performance.now();
|
17516
18347
|
// decrypt the subtitles
|
17517
|
-
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
18348
|
+
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
|
17518
18349
|
hls.trigger(Events.ERROR, {
|
17519
18350
|
type: ErrorTypes.MEDIA_ERROR,
|
17520
18351
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -17646,7 +18477,7 @@
|
|
17646
18477
|
_inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
|
17647
18478
|
function SubtitleTrackController(hls) {
|
17648
18479
|
var _this;
|
17649
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
18480
|
+
_this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
|
17650
18481
|
_this.media = null;
|
17651
18482
|
_this.tracks = [];
|
17652
18483
|
_this.groupIds = null;
|
@@ -17655,12 +18486,12 @@
|
|
17655
18486
|
_this.currentTrack = null;
|
17656
18487
|
_this.selectDefaultTrack = true;
|
17657
18488
|
_this.queuedDefaultTrack = -1;
|
17658
|
-
_this.asyncPollTrackChange = function () {
|
17659
|
-
return _this.pollTrackChange(0);
|
17660
|
-
};
|
17661
18489
|
_this.useTextTrackPolling = false;
|
17662
18490
|
_this.subtitlePollingInterval = -1;
|
17663
18491
|
_this._subtitleDisplay = true;
|
18492
|
+
_this.asyncPollTrackChange = function () {
|
18493
|
+
return _this.pollTrackChange(0);
|
18494
|
+
};
|
17664
18495
|
_this.onTextTracksChanged = function () {
|
17665
18496
|
if (!_this.useTextTrackPolling) {
|
17666
18497
|
self.clearInterval(_this.subtitlePollingInterval);
|
@@ -17696,6 +18527,7 @@
|
|
17696
18527
|
this.tracks.length = 0;
|
17697
18528
|
this.tracksInGroup.length = 0;
|
17698
18529
|
this.currentTrack = null;
|
18530
|
+
// @ts-ignore
|
17699
18531
|
this.onTextTracksChanged = this.asyncPollTrackChange = null;
|
17700
18532
|
_BasePlaylistControll.prototype.destroy.call(this);
|
17701
18533
|
};
|
@@ -18169,57 +19001,57 @@
|
|
18169
19001
|
}();
|
18170
19002
|
|
18171
19003
|
var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
|
18172
|
-
var BufferController = /*#__PURE__*/function () {
|
19004
|
+
var BufferController = /*#__PURE__*/function (_Logger) {
|
19005
|
+
_inheritsLoose(BufferController, _Logger);
|
18173
19006
|
function BufferController(hls) {
|
18174
|
-
var _this
|
19007
|
+
var _this;
|
19008
|
+
_this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
|
18175
19009
|
// The level details used to determine duration, target-duration and live
|
18176
|
-
|
19010
|
+
_this.details = null;
|
18177
19011
|
// cache the self generated object url to detect hijack of video tag
|
18178
|
-
|
19012
|
+
_this._objectUrl = null;
|
18179
19013
|
// A queue of buffer operations which require the SourceBuffer to not be updating upon execution
|
18180
|
-
|
19014
|
+
_this.operationQueue = void 0;
|
18181
19015
|
// References to event listeners for each SourceBuffer, so that they can be referenced for event removal
|
18182
|
-
|
18183
|
-
|
19016
|
+
_this.listeners = void 0;
|
19017
|
+
_this.hls = void 0;
|
18184
19018
|
// The number of BUFFER_CODEC events received before any sourceBuffers are created
|
18185
|
-
|
19019
|
+
_this.bufferCodecEventsExpected = 0;
|
18186
19020
|
// The total number of BUFFER_CODEC events received
|
18187
|
-
|
19021
|
+
_this._bufferCodecEventsTotal = 0;
|
18188
19022
|
// A reference to the attached media element
|
18189
|
-
|
19023
|
+
_this.media = null;
|
18190
19024
|
// A reference to the active media source
|
18191
|
-
|
19025
|
+
_this.mediaSource = null;
|
18192
19026
|
// Last MP3 audio chunk appended
|
18193
|
-
|
18194
|
-
|
19027
|
+
_this.lastMpegAudioChunk = null;
|
19028
|
+
_this.appendSource = void 0;
|
18195
19029
|
// counters
|
18196
|
-
|
19030
|
+
_this.appendErrors = {
|
18197
19031
|
audio: 0,
|
18198
19032
|
video: 0,
|
18199
19033
|
audiovideo: 0
|
18200
19034
|
};
|
18201
|
-
|
18202
|
-
|
18203
|
-
|
18204
|
-
|
18205
|
-
this.warn = void 0;
|
18206
|
-
this.error = void 0;
|
18207
|
-
this._onEndStreaming = function (event) {
|
19035
|
+
_this.tracks = {};
|
19036
|
+
_this.pendingTracks = {};
|
19037
|
+
_this.sourceBuffer = void 0;
|
19038
|
+
_this._onEndStreaming = function (event) {
|
18208
19039
|
if (!_this.hls) {
|
18209
19040
|
return;
|
18210
19041
|
}
|
18211
19042
|
_this.hls.pauseBuffering();
|
18212
19043
|
};
|
18213
|
-
|
19044
|
+
_this._onStartStreaming = function (event) {
|
18214
19045
|
if (!_this.hls) {
|
18215
19046
|
return;
|
18216
19047
|
}
|
18217
19048
|
_this.hls.resumeBuffering();
|
18218
19049
|
};
|
18219
19050
|
// Keep as arrow functions so that we can directly reference these functions directly as event listeners
|
18220
|
-
|
18221
|
-
var
|
18222
|
-
|
19051
|
+
_this._onMediaSourceOpen = function () {
|
19052
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
19053
|
+
media = _assertThisInitialize.media,
|
19054
|
+
mediaSource = _assertThisInitialize.mediaSource;
|
18223
19055
|
_this.log('Media source opened');
|
18224
19056
|
if (media) {
|
18225
19057
|
media.removeEventListener('emptied', _this._onMediaEmptied);
|
@@ -18235,27 +19067,25 @@
|
|
18235
19067
|
}
|
18236
19068
|
_this.checkPendingTracks();
|
18237
19069
|
};
|
18238
|
-
|
19070
|
+
_this._onMediaSourceClose = function () {
|
18239
19071
|
_this.log('Media source closed');
|
18240
19072
|
};
|
18241
|
-
|
19073
|
+
_this._onMediaSourceEnded = function () {
|
18242
19074
|
_this.log('Media source ended');
|
18243
19075
|
};
|
18244
|
-
|
18245
|
-
var
|
18246
|
-
|
19076
|
+
_this._onMediaEmptied = function () {
|
19077
|
+
var _assertThisInitialize2 = _assertThisInitialized(_this),
|
19078
|
+
mediaSrc = _assertThisInitialize2.mediaSrc,
|
19079
|
+
_objectUrl = _assertThisInitialize2._objectUrl;
|
18247
19080
|
if (mediaSrc !== _objectUrl) {
|
18248
|
-
|
19081
|
+
_this.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
|
18249
19082
|
}
|
18250
19083
|
};
|
18251
|
-
|
18252
|
-
|
18253
|
-
|
18254
|
-
|
18255
|
-
|
18256
|
-
this.error = logger.error.bind(logger, logPrefix);
|
18257
|
-
this._initSourceBuffer();
|
18258
|
-
this.registerListeners();
|
19084
|
+
_this.hls = hls;
|
19085
|
+
_this.appendSource = hls.config.preferManagedMediaSource;
|
19086
|
+
_this._initSourceBuffer();
|
19087
|
+
_this.registerListeners();
|
19088
|
+
return _this;
|
18259
19089
|
}
|
18260
19090
|
var _proto = BufferController.prototype;
|
18261
19091
|
_proto.hasSourceTypes = function hasSourceTypes() {
|
@@ -18267,6 +19097,12 @@
|
|
18267
19097
|
this.lastMpegAudioChunk = null;
|
18268
19098
|
// @ts-ignore
|
18269
19099
|
this.hls = null;
|
19100
|
+
// @ts-ignore
|
19101
|
+
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
19102
|
+
// @ts-ignore
|
19103
|
+
this._onMediaSourceEnded = null;
|
19104
|
+
// @ts-ignore
|
19105
|
+
this._onStartStreaming = this._onEndStreaming = null;
|
18270
19106
|
};
|
18271
19107
|
_proto.registerListeners = function registerListeners() {
|
18272
19108
|
var hls = this.hls;
|
@@ -18424,6 +19260,7 @@
|
|
18424
19260
|
_this2.resetBuffer(type);
|
18425
19261
|
});
|
18426
19262
|
this._initSourceBuffer();
|
19263
|
+
this.hls.resumeBuffering();
|
18427
19264
|
};
|
18428
19265
|
_proto.resetBuffer = function resetBuffer(type) {
|
18429
19266
|
var sb = this.sourceBuffer[type];
|
@@ -19127,7 +19964,7 @@
|
|
19127
19964
|
}
|
19128
19965
|
}]);
|
19129
19966
|
return BufferController;
|
19130
|
-
}();
|
19967
|
+
}(Logger);
|
19131
19968
|
function removeSourceChildren(node) {
|
19132
19969
|
var sourceChildren = node.querySelectorAll('source');
|
19133
19970
|
[].slice.call(sourceChildren).forEach(function (source) {
|
@@ -21566,14 +22403,12 @@
|
|
21566
22403
|
this.cea608Parser1 = this.cea608Parser2 = undefined;
|
21567
22404
|
};
|
21568
22405
|
_proto.initCea608Parsers = function initCea608Parsers() {
|
21569
|
-
|
21570
|
-
|
21571
|
-
|
21572
|
-
|
21573
|
-
|
21574
|
-
|
21575
|
-
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21576
|
-
}
|
22406
|
+
var channel1 = new OutputFilter(this, 'textTrack1');
|
22407
|
+
var channel2 = new OutputFilter(this, 'textTrack2');
|
22408
|
+
var channel3 = new OutputFilter(this, 'textTrack3');
|
22409
|
+
var channel4 = new OutputFilter(this, 'textTrack4');
|
22410
|
+
this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
|
22411
|
+
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21577
22412
|
};
|
21578
22413
|
_proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
|
21579
22414
|
// skip cues which overlap more than 50% with previously parsed time ranges
|
@@ -21808,7 +22643,7 @@
|
|
21808
22643
|
return t.label;
|
21809
22644
|
});
|
21810
22645
|
if (unusedTextTracks.length) {
|
21811
|
-
logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
|
22646
|
+
this.hls.logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
|
21812
22647
|
}
|
21813
22648
|
}
|
21814
22649
|
} else if (this.tracks.length) {
|
@@ -21854,23 +22689,20 @@
|
|
21854
22689
|
return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
|
21855
22690
|
};
|
21856
22691
|
_proto.onFragLoading = function onFragLoading(event, data) {
|
21857
|
-
this.initCea608Parsers();
|
21858
|
-
var cea608Parser1 = this.cea608Parser1,
|
21859
|
-
cea608Parser2 = this.cea608Parser2,
|
21860
|
-
lastCc = this.lastCc,
|
21861
|
-
lastSn = this.lastSn,
|
21862
|
-
lastPartIndex = this.lastPartIndex;
|
21863
|
-
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
21864
|
-
return;
|
21865
|
-
}
|
21866
22692
|
// if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
|
21867
|
-
if (data.frag.type === PlaylistLevelType.MAIN) {
|
22693
|
+
if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
|
21868
22694
|
var _data$part$index, _data$part;
|
22695
|
+
var cea608Parser1 = this.cea608Parser1,
|
22696
|
+
cea608Parser2 = this.cea608Parser2,
|
22697
|
+
lastSn = this.lastSn;
|
22698
|
+
if (!cea608Parser1 || !cea608Parser2) {
|
22699
|
+
return;
|
22700
|
+
}
|
21869
22701
|
var _data$frag = data.frag,
|
21870
22702
|
cc = _data$frag.cc,
|
21871
22703
|
sn = _data$frag.sn;
|
21872
|
-
var partIndex = (_data$part$index =
|
21873
|
-
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
|
22704
|
+
var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
22705
|
+
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === this.lastPartIndex + 1 || cc === this.lastCc)) {
|
21874
22706
|
cea608Parser1.reset();
|
21875
22707
|
cea608Parser2.reset();
|
21876
22708
|
}
|
@@ -21926,7 +22758,7 @@
|
|
21926
22758
|
frag: frag
|
21927
22759
|
});
|
21928
22760
|
}, function (error) {
|
21929
|
-
logger.log("Failed to parse IMSC1: " + error);
|
22761
|
+
hls.logger.log("Failed to parse IMSC1: " + error);
|
21930
22762
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
21931
22763
|
success: false,
|
21932
22764
|
frag: frag,
|
@@ -21964,7 +22796,7 @@
|
|
21964
22796
|
_this5._fallbackToIMSC1(frag, payload);
|
21965
22797
|
}
|
21966
22798
|
// Something went wrong while parsing. Trigger event with success false.
|
21967
|
-
logger.log("Failed to parse VTT cue: " + error);
|
22799
|
+
hls.logger.log("Failed to parse VTT cue: " + error);
|
21968
22800
|
if (missingInitPTS && maxAvCC > frag.cc) {
|
21969
22801
|
return;
|
21970
22802
|
}
|
@@ -22026,10 +22858,7 @@
|
|
22026
22858
|
this.captionsTracks = {};
|
22027
22859
|
};
|
22028
22860
|
_proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
|
22029
|
-
this.
|
22030
|
-
var cea608Parser1 = this.cea608Parser1,
|
22031
|
-
cea608Parser2 = this.cea608Parser2;
|
22032
|
-
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
22861
|
+
if (!this.enabled || !this.config.enableCEA708Captions) {
|
22033
22862
|
return;
|
22034
22863
|
}
|
22035
22864
|
var frag = data.frag,
|
@@ -22042,9 +22871,12 @@
|
|
22042
22871
|
for (var i = 0; i < samples.length; i++) {
|
22043
22872
|
var ccBytes = samples[i].bytes;
|
22044
22873
|
if (ccBytes) {
|
22874
|
+
if (!this.cea608Parser1) {
|
22875
|
+
this.initCea608Parsers();
|
22876
|
+
}
|
22045
22877
|
var ccdatas = this.extractCea608Data(ccBytes);
|
22046
|
-
cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22047
|
-
cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22878
|
+
this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22879
|
+
this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22048
22880
|
}
|
22049
22881
|
}
|
22050
22882
|
};
|
@@ -22236,7 +23068,7 @@
|
|
22236
23068
|
var hls = this.hls;
|
22237
23069
|
var maxLevel = this.getMaxLevel(levels.length - 1);
|
22238
23070
|
if (maxLevel !== this.autoLevelCapping) {
|
22239
|
-
logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
23071
|
+
hls.logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
22240
23072
|
}
|
22241
23073
|
hls.autoLevelCapping = maxLevel;
|
22242
23074
|
if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
|
@@ -22426,10 +23258,10 @@
|
|
22426
23258
|
totalDroppedFrames: droppedFrames
|
22427
23259
|
});
|
22428
23260
|
if (droppedFPS > 0) {
|
22429
|
-
// logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
23261
|
+
// hls.logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
22430
23262
|
if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
|
22431
23263
|
var currentLevel = hls.currentLevel;
|
22432
|
-
logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
23264
|
+
hls.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
22433
23265
|
if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
|
22434
23266
|
currentLevel = currentLevel - 1;
|
22435
23267
|
hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
|
@@ -22462,7 +23294,6 @@
|
|
22462
23294
|
return FPSController;
|
22463
23295
|
}();
|
22464
23296
|
|
22465
|
-
var LOGGER_PREFIX = '[eme]';
|
22466
23297
|
/**
|
22467
23298
|
* Controller to deal with encrypted media extensions (EME)
|
22468
23299
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
|
@@ -22470,26 +23301,122 @@
|
|
22470
23301
|
* @class
|
22471
23302
|
* @constructor
|
22472
23303
|
*/
|
22473
|
-
var EMEController = /*#__PURE__*/function () {
|
23304
|
+
var EMEController = /*#__PURE__*/function (_Logger) {
|
23305
|
+
_inheritsLoose(EMEController, _Logger);
|
22474
23306
|
function EMEController(hls) {
|
22475
|
-
|
22476
|
-
this.
|
22477
|
-
|
22478
|
-
|
22479
|
-
|
22480
|
-
|
22481
|
-
|
22482
|
-
|
22483
|
-
|
22484
|
-
|
22485
|
-
|
22486
|
-
|
22487
|
-
|
22488
|
-
|
22489
|
-
|
22490
|
-
|
22491
|
-
|
22492
|
-
|
23307
|
+
var _this;
|
23308
|
+
_this = _Logger.call(this, 'eme', hls.logger) || this;
|
23309
|
+
_this.hls = void 0;
|
23310
|
+
_this.config = void 0;
|
23311
|
+
_this.media = null;
|
23312
|
+
_this.keyFormatPromise = null;
|
23313
|
+
_this.keySystemAccessPromises = {};
|
23314
|
+
_this._requestLicenseFailureCount = 0;
|
23315
|
+
_this.mediaKeySessions = [];
|
23316
|
+
_this.keyIdToKeySessionPromise = {};
|
23317
|
+
_this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
23318
|
+
_this.onMediaEncrypted = function (event) {
|
23319
|
+
var initDataType = event.initDataType,
|
23320
|
+
initData = event.initData;
|
23321
|
+
_this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
23322
|
+
|
23323
|
+
// Ignore event when initData is null
|
23324
|
+
if (initData === null) {
|
23325
|
+
return;
|
23326
|
+
}
|
23327
|
+
var keyId;
|
23328
|
+
var keySystemDomain;
|
23329
|
+
if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
23330
|
+
// Match sinf keyId to playlist skd://keyId=
|
23331
|
+
var json = bin2str(new Uint8Array(initData));
|
23332
|
+
try {
|
23333
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
23334
|
+
var tenc = parseSinf(new Uint8Array(sinf));
|
23335
|
+
if (!tenc) {
|
23336
|
+
return;
|
23337
|
+
}
|
23338
|
+
keyId = tenc.subarray(8, 24);
|
23339
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
23340
|
+
} catch (error) {
|
23341
|
+
_this.warn('Failed to parse sinf "encrypted" event message initData');
|
23342
|
+
return;
|
23343
|
+
}
|
23344
|
+
} else {
|
23345
|
+
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
23346
|
+
var psshInfo = parsePssh(initData);
|
23347
|
+
if (psshInfo === null) {
|
23348
|
+
return;
|
23349
|
+
}
|
23350
|
+
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
23351
|
+
keyId = psshInfo.data.subarray(8, 24);
|
23352
|
+
}
|
23353
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
23354
|
+
}
|
23355
|
+
if (!keySystemDomain || !keyId) {
|
23356
|
+
return;
|
23357
|
+
}
|
23358
|
+
var keyIdHex = Hex.hexDump(keyId);
|
23359
|
+
var _assertThisInitialize = _assertThisInitialized(_this),
|
23360
|
+
keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
|
23361
|
+
mediaKeySessions = _assertThisInitialize.mediaKeySessions;
|
23362
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
23363
|
+
var _loop = function _loop() {
|
23364
|
+
// Match playlist key
|
23365
|
+
var keyContext = mediaKeySessions[i];
|
23366
|
+
var decryptdata = keyContext.decryptdata;
|
23367
|
+
if (decryptdata.pssh || !decryptdata.keyId) {
|
23368
|
+
return 0; // continue
|
23369
|
+
}
|
23370
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
23371
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
23372
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
23373
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
23374
|
+
decryptdata.pssh = new Uint8Array(initData);
|
23375
|
+
decryptdata.keyId = keyId;
|
23376
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
23377
|
+
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
23378
|
+
});
|
23379
|
+
return 1; // break
|
23380
|
+
}
|
23381
|
+
},
|
23382
|
+
_ret;
|
23383
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
23384
|
+
_ret = _loop();
|
23385
|
+
if (_ret === 0) continue;
|
23386
|
+
if (_ret === 1) break;
|
23387
|
+
}
|
23388
|
+
if (!keySessionContextPromise) {
|
23389
|
+
// Clear-lead key (not encountered in playlist)
|
23390
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
23391
|
+
var _keySystemToKeySystem;
|
23392
|
+
var keySystem = _ref.keySystem,
|
23393
|
+
mediaKeys = _ref.mediaKeys;
|
23394
|
+
_this.throwIfDestroyed();
|
23395
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
23396
|
+
decryptdata.pssh = new Uint8Array(initData);
|
23397
|
+
decryptdata.keyId = keyId;
|
23398
|
+
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23399
|
+
_this.throwIfDestroyed();
|
23400
|
+
var keySessionContext = _this.createMediaKeySessionContext({
|
23401
|
+
decryptdata: decryptdata,
|
23402
|
+
keySystem: keySystem,
|
23403
|
+
mediaKeys: mediaKeys
|
23404
|
+
});
|
23405
|
+
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
23406
|
+
});
|
23407
|
+
});
|
23408
|
+
}
|
23409
|
+
keySessionContextPromise.catch(function (error) {
|
23410
|
+
return _this.handleError(error);
|
23411
|
+
});
|
23412
|
+
};
|
23413
|
+
_this.onWaitingForKey = function (event) {
|
23414
|
+
_this.log("\"" + event.type + "\" event");
|
23415
|
+
};
|
23416
|
+
_this.hls = hls;
|
23417
|
+
_this.config = hls.config;
|
23418
|
+
_this.registerListeners();
|
23419
|
+
return _this;
|
22493
23420
|
}
|
22494
23421
|
var _proto = EMEController.prototype;
|
22495
23422
|
_proto.destroy = function destroy() {
|
@@ -22501,9 +23428,9 @@
|
|
22501
23428
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
22502
23429
|
config.drmSystems = config.drmSystemOptions = {};
|
22503
23430
|
// @ts-ignore
|
22504
|
-
this.hls = this.
|
23431
|
+
this.hls = this.config = this.keyIdToKeySessionPromise = null;
|
22505
23432
|
// @ts-ignore
|
22506
|
-
this.
|
23433
|
+
this.onMediaEncrypted = this.onWaitingForKey = null;
|
22507
23434
|
};
|
22508
23435
|
_proto.registerListeners = function registerListeners() {
|
22509
23436
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -22542,7 +23469,7 @@
|
|
22542
23469
|
}
|
22543
23470
|
};
|
22544
23471
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
22545
|
-
var
|
23472
|
+
var _this2 = this;
|
22546
23473
|
var levels = this.hls.levels;
|
22547
23474
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
22548
23475
|
return !!value && a.indexOf(value) === i;
|
@@ -22559,7 +23486,7 @@
|
|
22559
23486
|
return new Promise(function (resolve, reject) {
|
22560
23487
|
var attempt = function attempt(keySystems) {
|
22561
23488
|
var keySystem = keySystems.shift();
|
22562
|
-
|
23489
|
+
_this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
22563
23490
|
return resolve({
|
22564
23491
|
keySystem: keySystem,
|
22565
23492
|
mediaKeys: mediaKeys
|
@@ -22594,7 +23521,7 @@
|
|
22594
23521
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
22595
23522
|
};
|
22596
23523
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
22597
|
-
var
|
23524
|
+
var _this3 = this;
|
22598
23525
|
// This can throw, but is caught in event handler callpath
|
22599
23526
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
22600
23527
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -22606,23 +23533,23 @@
|
|
22606
23533
|
keySystemAccess: keySystemAccess
|
22607
23534
|
};
|
22608
23535
|
keySystemAccess.catch(function (error) {
|
22609
|
-
|
23536
|
+
_this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
22610
23537
|
});
|
22611
23538
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
22612
|
-
|
22613
|
-
var certificateRequest =
|
22614
|
-
|
23539
|
+
_this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
23540
|
+
var certificateRequest = _this3.fetchServerCertificate(keySystem);
|
23541
|
+
_this3.log("Create media-keys for \"" + keySystem + "\"");
|
22615
23542
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
22616
|
-
|
23543
|
+
_this3.log("Media-keys created for \"" + keySystem + "\"");
|
22617
23544
|
return certificateRequest.then(function (certificate) {
|
22618
23545
|
if (certificate) {
|
22619
|
-
return
|
23546
|
+
return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
22620
23547
|
}
|
22621
23548
|
return mediaKeys;
|
22622
23549
|
});
|
22623
23550
|
});
|
22624
23551
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
22625
|
-
|
23552
|
+
_this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
22626
23553
|
});
|
22627
23554
|
return _keySystemAccessPromises.mediaKeys;
|
22628
23555
|
});
|
@@ -22631,10 +23558,10 @@
|
|
22631
23558
|
return keySystemAccessPromises.mediaKeys;
|
22632
23559
|
});
|
22633
23560
|
};
|
22634
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
22635
|
-
var decryptdata =
|
22636
|
-
keySystem =
|
22637
|
-
mediaKeys =
|
23561
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
|
23562
|
+
var decryptdata = _ref2.decryptdata,
|
23563
|
+
keySystem = _ref2.keySystem,
|
23564
|
+
mediaKeys = _ref2.mediaKeys;
|
22638
23565
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
22639
23566
|
var mediaKeysSession = mediaKeys.createSession();
|
22640
23567
|
var mediaKeySessionContext = {
|
@@ -22683,14 +23610,14 @@
|
|
22683
23610
|
return this.keyFormatPromise;
|
22684
23611
|
};
|
22685
23612
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
22686
|
-
var
|
23613
|
+
var _this4 = this;
|
22687
23614
|
return new Promise(function (resolve, reject) {
|
22688
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
23615
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
|
22689
23616
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
22690
23617
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
22691
23618
|
});
|
22692
|
-
return
|
22693
|
-
var keySystem =
|
23619
|
+
return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
|
23620
|
+
var keySystem = _ref3.keySystem;
|
22694
23621
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
22695
23622
|
if (keySystemFormat) {
|
22696
23623
|
resolve(keySystemFormat);
|
@@ -22701,31 +23628,31 @@
|
|
22701
23628
|
});
|
22702
23629
|
};
|
22703
23630
|
_proto.loadKey = function loadKey(data) {
|
22704
|
-
var
|
23631
|
+
var _this5 = this;
|
22705
23632
|
var decryptdata = data.keyInfo.decryptdata;
|
22706
23633
|
var keyId = this.getKeyIdString(decryptdata);
|
22707
23634
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
22708
23635
|
this.log("Starting session for key " + keyDetails);
|
22709
23636
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
22710
23637
|
if (!keySessionContextPromise) {
|
22711
|
-
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (
|
22712
|
-
var keySystem =
|
22713
|
-
mediaKeys =
|
22714
|
-
|
22715
|
-
|
22716
|
-
return
|
22717
|
-
|
22718
|
-
var keySessionContext =
|
23638
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
|
23639
|
+
var keySystem = _ref4.keySystem,
|
23640
|
+
mediaKeys = _ref4.mediaKeys;
|
23641
|
+
_this5.throwIfDestroyed();
|
23642
|
+
_this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
23643
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23644
|
+
_this5.throwIfDestroyed();
|
23645
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22719
23646
|
keySystem: keySystem,
|
22720
23647
|
mediaKeys: mediaKeys,
|
22721
23648
|
decryptdata: decryptdata
|
22722
23649
|
});
|
22723
23650
|
var scheme = 'cenc';
|
22724
|
-
return
|
23651
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
22725
23652
|
});
|
22726
23653
|
});
|
22727
23654
|
keySessionContextPromise.catch(function (error) {
|
22728
|
-
return
|
23655
|
+
return _this5.handleError(error);
|
22729
23656
|
});
|
22730
23657
|
}
|
22731
23658
|
return keySessionContextPromise;
|
@@ -22751,128 +23678,30 @@
|
|
22751
23678
|
});
|
22752
23679
|
}
|
22753
23680
|
};
|
22754
|
-
_proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
|
22755
|
-
var keyId = this.getKeyIdString(decryptdata);
|
22756
|
-
var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
|
22757
|
-
if (!mediaKeySessionContext) {
|
22758
|
-
var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
|
22759
|
-
var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
|
22760
|
-
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22761
|
-
}
|
22762
|
-
return mediaKeySessionContext;
|
22763
|
-
};
|
22764
|
-
_proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
|
22765
|
-
if (!keySystemsToAttempt.length) {
|
22766
|
-
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
22767
|
-
}
|
22768
|
-
if (keySystemsToAttempt.length === 0) {
|
22769
|
-
throw new EMEKeyError({
|
22770
|
-
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
22771
|
-
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
22772
|
-
fatal: true
|
22773
|
-
}, "Missing key-system license configuration options " + JSON.stringify({
|
22774
|
-
drmSystems: this.config.drmSystems
|
22775
|
-
}));
|
22776
|
-
}
|
22777
|
-
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22778
|
-
};
|
22779
|
-
_proto._onMediaEncrypted = function _onMediaEncrypted(event) {
|
22780
|
-
var _this5 = this;
|
22781
|
-
var initDataType = event.initDataType,
|
22782
|
-
initData = event.initData;
|
22783
|
-
this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
22784
|
-
|
22785
|
-
// Ignore event when initData is null
|
22786
|
-
if (initData === null) {
|
22787
|
-
return;
|
22788
|
-
}
|
22789
|
-
var keyId;
|
22790
|
-
var keySystemDomain;
|
22791
|
-
if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22792
|
-
// Match sinf keyId to playlist skd://keyId=
|
22793
|
-
var json = bin2str(new Uint8Array(initData));
|
22794
|
-
try {
|
22795
|
-
var sinf = base64Decode(JSON.parse(json).sinf);
|
22796
|
-
var tenc = parseSinf(new Uint8Array(sinf));
|
22797
|
-
if (!tenc) {
|
22798
|
-
return;
|
22799
|
-
}
|
22800
|
-
keyId = tenc.subarray(8, 24);
|
22801
|
-
keySystemDomain = KeySystems.FAIRPLAY;
|
22802
|
-
} catch (error) {
|
22803
|
-
this.warn('Failed to parse sinf "encrypted" event message initData');
|
22804
|
-
return;
|
22805
|
-
}
|
22806
|
-
} else {
|
22807
|
-
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22808
|
-
var psshInfo = parsePssh(initData);
|
22809
|
-
if (psshInfo === null) {
|
22810
|
-
return;
|
22811
|
-
}
|
22812
|
-
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22813
|
-
keyId = psshInfo.data.subarray(8, 24);
|
22814
|
-
}
|
22815
|
-
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22816
|
-
}
|
22817
|
-
if (!keySystemDomain || !keyId) {
|
22818
|
-
return;
|
22819
|
-
}
|
22820
|
-
var keyIdHex = Hex.hexDump(keyId);
|
22821
|
-
var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
|
22822
|
-
mediaKeySessions = this.mediaKeySessions;
|
22823
|
-
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22824
|
-
var _loop = function _loop() {
|
22825
|
-
// Match playlist key
|
22826
|
-
var keyContext = mediaKeySessions[i];
|
22827
|
-
var decryptdata = keyContext.decryptdata;
|
22828
|
-
if (decryptdata.pssh || !decryptdata.keyId) {
|
22829
|
-
return 0; // continue
|
22830
|
-
}
|
22831
|
-
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22832
|
-
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22833
|
-
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22834
|
-
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22835
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22836
|
-
decryptdata.keyId = keyId;
|
22837
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22838
|
-
return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22839
|
-
});
|
22840
|
-
return 1; // break
|
22841
|
-
}
|
22842
|
-
},
|
22843
|
-
_ret;
|
22844
|
-
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22845
|
-
_ret = _loop();
|
22846
|
-
if (_ret === 0) continue;
|
22847
|
-
if (_ret === 1) break;
|
22848
|
-
}
|
22849
|
-
if (!keySessionContextPromise) {
|
22850
|
-
// Clear-lead key (not encountered in playlist)
|
22851
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
|
22852
|
-
var _keySystemToKeySystem;
|
22853
|
-
var keySystem = _ref4.keySystem,
|
22854
|
-
mediaKeys = _ref4.mediaKeys;
|
22855
|
-
_this5.throwIfDestroyed();
|
22856
|
-
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22857
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22858
|
-
decryptdata.keyId = keyId;
|
22859
|
-
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22860
|
-
_this5.throwIfDestroyed();
|
22861
|
-
var keySessionContext = _this5.createMediaKeySessionContext({
|
22862
|
-
decryptdata: decryptdata,
|
22863
|
-
keySystem: keySystem,
|
22864
|
-
mediaKeys: mediaKeys
|
22865
|
-
});
|
22866
|
-
return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22867
|
-
});
|
22868
|
-
});
|
23681
|
+
_proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
|
23682
|
+
var keyId = this.getKeyIdString(decryptdata);
|
23683
|
+
var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
|
23684
|
+
if (!mediaKeySessionContext) {
|
23685
|
+
var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
|
23686
|
+
var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
|
23687
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22869
23688
|
}
|
22870
|
-
|
22871
|
-
return _this5.handleError(error);
|
22872
|
-
});
|
23689
|
+
return mediaKeySessionContext;
|
22873
23690
|
};
|
22874
|
-
_proto.
|
22875
|
-
|
23691
|
+
_proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
|
23692
|
+
if (!keySystemsToAttempt.length) {
|
23693
|
+
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
23694
|
+
}
|
23695
|
+
if (keySystemsToAttempt.length === 0) {
|
23696
|
+
throw new EMEKeyError({
|
23697
|
+
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
23698
|
+
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
23699
|
+
fatal: true
|
23700
|
+
}, "Missing key-system license configuration options " + JSON.stringify({
|
23701
|
+
drmSystems: this.config.drmSystems
|
23702
|
+
}));
|
23703
|
+
}
|
23704
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22876
23705
|
};
|
22877
23706
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
22878
23707
|
var _this6 = this;
|
@@ -23329,7 +24158,7 @@
|
|
23329
24158
|
}
|
23330
24159
|
};
|
23331
24160
|
return EMEController;
|
23332
|
-
}();
|
24161
|
+
}(Logger);
|
23333
24162
|
EMEController.CDMCleanupPromise = void 0;
|
23334
24163
|
var EMEKeyError = /*#__PURE__*/function (_Error) {
|
23335
24164
|
_inheritsLoose(EMEKeyError, _Error);
|
@@ -23477,18 +24306,6 @@
|
|
23477
24306
|
this.params = params;
|
23478
24307
|
};
|
23479
24308
|
|
23480
|
-
/**
|
23481
|
-
* A class to represent structured field tokens when `Symbol` is not available.
|
23482
|
-
*
|
23483
|
-
* @group Structured Field
|
23484
|
-
*
|
23485
|
-
* @beta
|
23486
|
-
*/
|
23487
|
-
var SfToken = function SfToken(description) {
|
23488
|
-
this.description = void 0;
|
23489
|
-
this.description = description;
|
23490
|
-
};
|
23491
|
-
|
23492
24309
|
var DICT = 'Dict';
|
23493
24310
|
|
23494
24311
|
function format(value) {
|
@@ -23512,29 +24329,25 @@
|
|
23512
24329
|
});
|
23513
24330
|
}
|
23514
24331
|
|
23515
|
-
|
23516
|
-
|
23517
|
-
var BOOLEAN = 'Boolean';
|
23518
|
-
|
23519
|
-
var BYTES = 'Byte Sequence';
|
23520
|
-
|
23521
|
-
var DECIMAL = 'Decimal';
|
23522
|
-
|
23523
|
-
var INTEGER = 'Integer';
|
23524
|
-
|
23525
|
-
function isInvalidInt(value) {
|
23526
|
-
return value < -999999999999999 || 999999999999999 < value;
|
24332
|
+
function serializeError(src, type, cause) {
|
24333
|
+
return throwError('serialize', src, type, cause);
|
23527
24334
|
}
|
23528
24335
|
|
23529
|
-
|
23530
|
-
|
23531
|
-
|
24336
|
+
/**
|
24337
|
+
* A class to represent structured field tokens when `Symbol` is not available.
|
24338
|
+
*
|
24339
|
+
* @group Structured Field
|
24340
|
+
*
|
24341
|
+
* @beta
|
24342
|
+
*/
|
24343
|
+
var SfToken = function SfToken(description) {
|
24344
|
+
this.description = void 0;
|
24345
|
+
this.description = description;
|
24346
|
+
};
|
23532
24347
|
|
23533
|
-
var
|
24348
|
+
var BARE_ITEM = 'Bare Item';
|
23534
24349
|
|
23535
|
-
|
23536
|
-
return throwError('serialize', src, type, cause);
|
23537
|
-
}
|
24350
|
+
var BOOLEAN = 'Boolean';
|
23538
24351
|
|
23539
24352
|
// 4.1.9. Serializing a Boolean
|
23540
24353
|
//
|
@@ -23573,6 +24386,8 @@
|
|
23573
24386
|
return btoa(String.fromCharCode.apply(String, binary));
|
23574
24387
|
}
|
23575
24388
|
|
24389
|
+
var BYTES = 'Byte Sequence';
|
24390
|
+
|
23576
24391
|
// 4.1.8. Serializing a Byte Sequence
|
23577
24392
|
//
|
23578
24393
|
// Given a Byte Sequence as input_bytes, return an ASCII string suitable
|
@@ -23604,6 +24419,12 @@
|
|
23604
24419
|
return ":" + base64encode(value) + ":";
|
23605
24420
|
}
|
23606
24421
|
|
24422
|
+
var INTEGER = 'Integer';
|
24423
|
+
|
24424
|
+
function isInvalidInt(value) {
|
24425
|
+
return value < -999999999999999 || 999999999999999 < value;
|
24426
|
+
}
|
24427
|
+
|
23607
24428
|
// 4.1.4. Serializing an Integer
|
23608
24429
|
//
|
23609
24430
|
// Given an Integer as input_integer, return an ASCII string suitable
|
@@ -23669,6 +24490,8 @@
|
|
23669
24490
|
}
|
23670
24491
|
}
|
23671
24492
|
|
24493
|
+
var DECIMAL = 'Decimal';
|
24494
|
+
|
23672
24495
|
// 4.1.5. Serializing a Decimal
|
23673
24496
|
//
|
23674
24497
|
// Given a decimal number as input_decimal, return an ASCII string
|
@@ -23714,6 +24537,8 @@
|
|
23714
24537
|
|
23715
24538
|
var STRING = 'String';
|
23716
24539
|
|
24540
|
+
var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
|
24541
|
+
|
23717
24542
|
// 4.1.6. Serializing a String
|
23718
24543
|
//
|
23719
24544
|
// Given a String as input_string, return an ASCII string suitable for
|
@@ -23749,6 +24574,8 @@
|
|
23749
24574
|
return symbol.description || symbol.toString().slice(7, -1);
|
23750
24575
|
}
|
23751
24576
|
|
24577
|
+
var TOKEN = 'Token';
|
24578
|
+
|
23752
24579
|
function serializeToken(token) {
|
23753
24580
|
var value = symbolToStr(token);
|
23754
24581
|
if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
|
@@ -23816,6 +24643,8 @@
|
|
23816
24643
|
}
|
23817
24644
|
}
|
23818
24645
|
|
24646
|
+
var KEY = 'Key';
|
24647
|
+
|
23819
24648
|
// 4.1.1.3. Serializing a Key
|
23820
24649
|
//
|
23821
24650
|
// Given a key as input_key, return an ASCII string suitable for use in
|
@@ -24067,36 +24896,6 @@
|
|
24067
24896
|
return toPath.join('/');
|
24068
24897
|
}
|
24069
24898
|
|
24070
|
-
/**
|
24071
|
-
* Generate a random v4 UUID
|
24072
|
-
*
|
24073
|
-
* @returns A random v4 UUID
|
24074
|
-
*
|
24075
|
-
* @group Utils
|
24076
|
-
*
|
24077
|
-
* @beta
|
24078
|
-
*/
|
24079
|
-
function uuid() {
|
24080
|
-
try {
|
24081
|
-
return crypto.randomUUID();
|
24082
|
-
} catch (error) {
|
24083
|
-
try {
|
24084
|
-
var url = URL.createObjectURL(new Blob());
|
24085
|
-
var _uuid = url.toString();
|
24086
|
-
URL.revokeObjectURL(url);
|
24087
|
-
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
24088
|
-
} catch (error) {
|
24089
|
-
var dt = new Date().getTime();
|
24090
|
-
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
24091
|
-
var r = (dt + Math.random() * 16) % 16 | 0;
|
24092
|
-
dt = Math.floor(dt / 16);
|
24093
|
-
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
24094
|
-
});
|
24095
|
-
return _uuid2;
|
24096
|
-
}
|
24097
|
-
}
|
24098
|
-
}
|
24099
|
-
|
24100
24899
|
var toRounded = function toRounded(value) {
|
24101
24900
|
return Math.round(value);
|
24102
24901
|
};
|
@@ -24341,6 +25140,36 @@
|
|
24341
25140
|
return "" + url + separator + query;
|
24342
25141
|
}
|
24343
25142
|
|
25143
|
+
/**
|
25144
|
+
* Generate a random v4 UUID
|
25145
|
+
*
|
25146
|
+
* @returns A random v4 UUID
|
25147
|
+
*
|
25148
|
+
* @group Utils
|
25149
|
+
*
|
25150
|
+
* @beta
|
25151
|
+
*/
|
25152
|
+
function uuid() {
|
25153
|
+
try {
|
25154
|
+
return crypto.randomUUID();
|
25155
|
+
} catch (error) {
|
25156
|
+
try {
|
25157
|
+
var url = URL.createObjectURL(new Blob());
|
25158
|
+
var _uuid = url.toString();
|
25159
|
+
URL.revokeObjectURL(url);
|
25160
|
+
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
25161
|
+
} catch (error) {
|
25162
|
+
var dt = new Date().getTime();
|
25163
|
+
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
25164
|
+
var r = (dt + Math.random() * 16) % 16 | 0;
|
25165
|
+
dt = Math.floor(dt / 16);
|
25166
|
+
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
25167
|
+
});
|
25168
|
+
return _uuid2;
|
25169
|
+
}
|
25170
|
+
}
|
25171
|
+
}
|
25172
|
+
|
24344
25173
|
/**
|
24345
25174
|
* Controller to deal with Common Media Client Data (CMCD)
|
24346
25175
|
* @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
|
@@ -24405,6 +25234,12 @@
|
|
24405
25234
|
data.tb = _this.getTopBandwidth(ot) / 1000;
|
24406
25235
|
data.bl = _this.getBufferLength(ot);
|
24407
25236
|
}
|
25237
|
+
var next = _this.getNextFrag(fragment);
|
25238
|
+
if (next) {
|
25239
|
+
if (next.url && next.url !== fragment.url) {
|
25240
|
+
data.nor = next.url;
|
25241
|
+
}
|
25242
|
+
}
|
24408
25243
|
_this.apply(context, data);
|
24409
25244
|
} catch (error) {
|
24410
25245
|
logger.warn('Could not generate segment CMCD data.', error);
|
@@ -24499,7 +25334,7 @@
|
|
24499
25334
|
data.su = this.buffering;
|
24500
25335
|
}
|
24501
25336
|
|
24502
|
-
// TODO: Implement rtp, nrr,
|
25337
|
+
// TODO: Implement rtp, nrr, dl
|
24503
25338
|
|
24504
25339
|
var includeKeys = this.includeKeys;
|
24505
25340
|
if (includeKeys) {
|
@@ -24508,18 +25343,31 @@
|
|
24508
25343
|
return acc;
|
24509
25344
|
}, {});
|
24510
25345
|
}
|
25346
|
+
var options = {
|
25347
|
+
baseUrl: context.url
|
25348
|
+
};
|
24511
25349
|
if (this.useHeaders) {
|
24512
25350
|
if (!context.headers) {
|
24513
25351
|
context.headers = {};
|
24514
25352
|
}
|
24515
|
-
appendCmcdHeaders(context.headers, data);
|
25353
|
+
appendCmcdHeaders(context.headers, data, options);
|
24516
25354
|
} else {
|
24517
|
-
context.url = appendCmcdQuery(context.url, data);
|
25355
|
+
context.url = appendCmcdQuery(context.url, data, options);
|
24518
25356
|
}
|
24519
25357
|
};
|
25358
|
+
_proto.getNextFrag = function getNextFrag(fragment) {
|
25359
|
+
var _this$hls$levels$frag;
|
25360
|
+
var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
|
25361
|
+
if (levelDetails) {
|
25362
|
+
var index = fragment.sn - levelDetails.startSN;
|
25363
|
+
return levelDetails.fragments[index + 1];
|
25364
|
+
}
|
25365
|
+
return undefined;
|
25366
|
+
}
|
25367
|
+
|
24520
25368
|
/**
|
24521
25369
|
* The CMCD object type.
|
24522
|
-
|
25370
|
+
*/;
|
24523
25371
|
_proto.getObjectType = function getObjectType(fragment) {
|
24524
25372
|
var type = fragment.type;
|
24525
25373
|
if (type === 'subtitle') {
|
@@ -24655,26 +25503,28 @@
|
|
24655
25503
|
}();
|
24656
25504
|
|
24657
25505
|
var PATHWAY_PENALTY_DURATION_MS = 300000;
|
24658
|
-
var ContentSteeringController = /*#__PURE__*/function () {
|
25506
|
+
var ContentSteeringController = /*#__PURE__*/function (_Logger) {
|
25507
|
+
_inheritsLoose(ContentSteeringController, _Logger);
|
24659
25508
|
function ContentSteeringController(hls) {
|
24660
|
-
|
24661
|
-
this.
|
24662
|
-
|
24663
|
-
|
24664
|
-
|
24665
|
-
|
24666
|
-
|
24667
|
-
|
24668
|
-
|
24669
|
-
|
24670
|
-
|
24671
|
-
|
24672
|
-
|
24673
|
-
|
24674
|
-
|
24675
|
-
|
24676
|
-
|
24677
|
-
|
25509
|
+
var _this;
|
25510
|
+
_this = _Logger.call(this, 'content-steering', hls.logger) || this;
|
25511
|
+
_this.hls = void 0;
|
25512
|
+
_this.loader = null;
|
25513
|
+
_this.uri = null;
|
25514
|
+
_this.pathwayId = '.';
|
25515
|
+
_this.pathwayPriority = null;
|
25516
|
+
_this.timeToLoad = 300;
|
25517
|
+
_this.reloadTimer = -1;
|
25518
|
+
_this.updated = 0;
|
25519
|
+
_this.started = false;
|
25520
|
+
_this.enabled = true;
|
25521
|
+
_this.levels = null;
|
25522
|
+
_this.audioTracks = null;
|
25523
|
+
_this.subtitleTracks = null;
|
25524
|
+
_this.penalizedPathways = {};
|
25525
|
+
_this.hls = hls;
|
25526
|
+
_this.registerListeners();
|
25527
|
+
return _this;
|
24678
25528
|
}
|
24679
25529
|
var _proto = ContentSteeringController.prototype;
|
24680
25530
|
_proto.registerListeners = function registerListeners() {
|
@@ -24795,7 +25645,7 @@
|
|
24795
25645
|
errorAction.resolved = this.pathwayId !== errorPathway;
|
24796
25646
|
}
|
24797
25647
|
if (!errorAction.resolved) {
|
24798
|
-
|
25648
|
+
this.warn("Could not resolve " + data.details + " (\"" + data.error.message + "\") with content-steering for Pathway: " + errorPathway + " levels: " + (levels ? levels.length : levels) + " priorities: " + JSON.stringify(pathwayPriority) + " penalized: " + JSON.stringify(this.penalizedPathways));
|
24799
25649
|
}
|
24800
25650
|
}
|
24801
25651
|
};
|
@@ -24875,7 +25725,7 @@
|
|
24875
25725
|
return defaultPathway;
|
24876
25726
|
};
|
24877
25727
|
_proto.clonePathways = function clonePathways(pathwayClones) {
|
24878
|
-
var
|
25728
|
+
var _this2 = this;
|
24879
25729
|
var levels = this.levels;
|
24880
25730
|
if (!levels) {
|
24881
25731
|
return;
|
@@ -24891,7 +25741,7 @@
|
|
24891
25741
|
})) {
|
24892
25742
|
return;
|
24893
25743
|
}
|
24894
|
-
var clonedVariants =
|
25744
|
+
var clonedVariants = _this2.getLevelsForPathway(baseId).map(function (baseLevel) {
|
24895
25745
|
var attributes = new AttrList(baseLevel.attrs);
|
24896
25746
|
attributes['PATHWAY-ID'] = cloneId;
|
24897
25747
|
var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
|
@@ -24928,12 +25778,12 @@
|
|
24928
25778
|
return clonedLevel;
|
24929
25779
|
});
|
24930
25780
|
levels.push.apply(levels, clonedVariants);
|
24931
|
-
cloneRenditionGroups(
|
24932
|
-
cloneRenditionGroups(
|
25781
|
+
cloneRenditionGroups(_this2.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
|
25782
|
+
cloneRenditionGroups(_this2.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
|
24933
25783
|
});
|
24934
25784
|
};
|
24935
25785
|
_proto.loadSteeringManifest = function loadSteeringManifest(uri) {
|
24936
|
-
var
|
25786
|
+
var _this3 = this;
|
24937
25787
|
var config = this.hls.config;
|
24938
25788
|
var Loader = config.loader;
|
24939
25789
|
if (this.loader) {
|
@@ -24968,87 +25818,87 @@
|
|
24968
25818
|
};
|
24969
25819
|
var callbacks = {
|
24970
25820
|
onSuccess: function onSuccess(response, stats, context, networkDetails) {
|
24971
|
-
|
25821
|
+
_this3.log("Loaded steering manifest: \"" + url + "\"");
|
24972
25822
|
var steeringData = response.data;
|
24973
|
-
if (steeringData.VERSION !== 1) {
|
24974
|
-
|
25823
|
+
if ((steeringData == null ? void 0 : steeringData.VERSION) !== 1) {
|
25824
|
+
_this3.log("Steering VERSION " + steeringData.VERSION + " not supported!");
|
24975
25825
|
return;
|
24976
25826
|
}
|
24977
|
-
|
24978
|
-
|
25827
|
+
_this3.updated = performance.now();
|
25828
|
+
_this3.timeToLoad = steeringData.TTL;
|
24979
25829
|
var reloadUri = steeringData['RELOAD-URI'],
|
24980
25830
|
pathwayClones = steeringData['PATHWAY-CLONES'],
|
24981
25831
|
pathwayPriority = steeringData['PATHWAY-PRIORITY'];
|
24982
25832
|
if (reloadUri) {
|
24983
25833
|
try {
|
24984
|
-
|
25834
|
+
_this3.uri = new self.URL(reloadUri, url).href;
|
24985
25835
|
} catch (error) {
|
24986
|
-
|
24987
|
-
|
25836
|
+
_this3.enabled = false;
|
25837
|
+
_this3.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
|
24988
25838
|
return;
|
24989
25839
|
}
|
24990
25840
|
}
|
24991
|
-
|
25841
|
+
_this3.scheduleRefresh(_this3.uri || context.url);
|
24992
25842
|
if (pathwayClones) {
|
24993
|
-
|
25843
|
+
_this3.clonePathways(pathwayClones);
|
24994
25844
|
}
|
24995
25845
|
var loadedSteeringData = {
|
24996
25846
|
steeringManifest: steeringData,
|
24997
25847
|
url: url.toString()
|
24998
25848
|
};
|
24999
|
-
|
25849
|
+
_this3.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
|
25000
25850
|
if (pathwayPriority) {
|
25001
|
-
|
25851
|
+
_this3.updatePathwayPriority(pathwayPriority);
|
25002
25852
|
}
|
25003
25853
|
},
|
25004
25854
|
onError: function onError(error, context, networkDetails, stats) {
|
25005
|
-
|
25006
|
-
|
25855
|
+
_this3.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
|
25856
|
+
_this3.stopLoad();
|
25007
25857
|
if (error.code === 410) {
|
25008
|
-
|
25009
|
-
|
25858
|
+
_this3.enabled = false;
|
25859
|
+
_this3.log("Steering manifest " + context.url + " no longer available");
|
25010
25860
|
return;
|
25011
25861
|
}
|
25012
|
-
var ttl =
|
25862
|
+
var ttl = _this3.timeToLoad * 1000;
|
25013
25863
|
if (error.code === 429) {
|
25014
|
-
var loader =
|
25864
|
+
var loader = _this3.loader;
|
25015
25865
|
if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
|
25016
25866
|
var retryAfter = loader.getResponseHeader('Retry-After');
|
25017
25867
|
if (retryAfter) {
|
25018
25868
|
ttl = parseFloat(retryAfter) * 1000;
|
25019
25869
|
}
|
25020
25870
|
}
|
25021
|
-
|
25871
|
+
_this3.log("Steering manifest " + context.url + " rate limited");
|
25022
25872
|
return;
|
25023
25873
|
}
|
25024
|
-
|
25874
|
+
_this3.scheduleRefresh(_this3.uri || context.url, ttl);
|
25025
25875
|
},
|
25026
25876
|
onTimeout: function onTimeout(stats, context, networkDetails) {
|
25027
|
-
|
25028
|
-
|
25877
|
+
_this3.log("Timeout loading steering manifest (" + context.url + ")");
|
25878
|
+
_this3.scheduleRefresh(_this3.uri || context.url);
|
25029
25879
|
}
|
25030
25880
|
};
|
25031
25881
|
this.log("Requesting steering manifest: " + url);
|
25032
25882
|
this.loader.load(context, loaderConfig, callbacks);
|
25033
25883
|
};
|
25034
25884
|
_proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
|
25035
|
-
var
|
25885
|
+
var _this4 = this;
|
25036
25886
|
if (ttlMs === void 0) {
|
25037
25887
|
ttlMs = this.timeToLoad * 1000;
|
25038
25888
|
}
|
25039
25889
|
this.clearTimeout();
|
25040
25890
|
this.reloadTimer = self.setTimeout(function () {
|
25041
|
-
var
|
25042
|
-
var media = (
|
25891
|
+
var _this4$hls;
|
25892
|
+
var media = (_this4$hls = _this4.hls) == null ? void 0 : _this4$hls.media;
|
25043
25893
|
if (media && !media.ended) {
|
25044
|
-
|
25894
|
+
_this4.loadSteeringManifest(uri);
|
25045
25895
|
return;
|
25046
25896
|
}
|
25047
|
-
|
25897
|
+
_this4.scheduleRefresh(uri, _this4.timeToLoad * 1000);
|
25048
25898
|
}, ttlMs);
|
25049
25899
|
};
|
25050
25900
|
return ContentSteeringController;
|
25051
|
-
}();
|
25901
|
+
}(Logger);
|
25052
25902
|
function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
|
25053
25903
|
if (!tracks) {
|
25054
25904
|
return;
|
@@ -25948,7 +26798,7 @@
|
|
25948
26798
|
/**
|
25949
26799
|
* @ignore
|
25950
26800
|
*/
|
25951
|
-
function mergeConfig(defaultConfig, userConfig) {
|
26801
|
+
function mergeConfig(defaultConfig, userConfig, logger) {
|
25952
26802
|
if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
|
25953
26803
|
throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
|
25954
26804
|
}
|
@@ -26018,7 +26868,7 @@
|
|
26018
26868
|
/**
|
26019
26869
|
* @ignore
|
26020
26870
|
*/
|
26021
|
-
function enableStreamingMode(config) {
|
26871
|
+
function enableStreamingMode(config, logger) {
|
26022
26872
|
var currentLoader = config.loader;
|
26023
26873
|
if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
|
26024
26874
|
// If a developer has configured their own loader, respect that choice
|
@@ -26035,12 +26885,11 @@
|
|
26035
26885
|
}
|
26036
26886
|
}
|
26037
26887
|
|
26038
|
-
var chromeOrFirefox;
|
26039
26888
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
26040
26889
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
26041
26890
|
function LevelController(hls, contentSteeringController) {
|
26042
26891
|
var _this;
|
26043
|
-
_this = _BasePlaylistControll.call(this, hls, '
|
26892
|
+
_this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
|
26044
26893
|
_this._levels = [];
|
26045
26894
|
_this._firstLevel = -1;
|
26046
26895
|
_this._maxAutoLevel = -1;
|
@@ -26109,21 +26958,13 @@
|
|
26109
26958
|
var videoCodecFound = false;
|
26110
26959
|
var audioCodecFound = false;
|
26111
26960
|
data.levels.forEach(function (levelParsed) {
|
26112
|
-
var
|
26961
|
+
var _videoCodec;
|
26113
26962
|
var attributes = levelParsed.attrs;
|
26114
|
-
|
26115
|
-
// erase audio codec info if browser does not support mp4a.40.34.
|
26116
|
-
// demuxer will autodetect codec and fallback to mpeg/audio
|
26117
26963
|
var audioCodec = levelParsed.audioCodec,
|
26118
26964
|
videoCodec = levelParsed.videoCodec;
|
26119
|
-
if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
|
26120
|
-
chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
|
26121
|
-
if (chromeOrFirefox) {
|
26122
|
-
levelParsed.audioCodec = audioCodec = undefined;
|
26123
|
-
}
|
26124
|
-
}
|
26125
26965
|
if (audioCodec) {
|
26126
|
-
|
26966
|
+
// Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
|
26967
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
26127
26968
|
}
|
26128
26969
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
26129
26970
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -26731,6 +27572,8 @@
|
|
26731
27572
|
}
|
26732
27573
|
return this.loadKeyEME(keyInfo, frag);
|
26733
27574
|
case 'AES-128':
|
27575
|
+
case 'AES-256':
|
27576
|
+
case 'AES-256-CTR':
|
26734
27577
|
return this.loadKeyHTTP(keyInfo, frag);
|
26735
27578
|
default:
|
26736
27579
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -26870,21 +27713,26 @@
|
|
26870
27713
|
var MAX_START_GAP_JUMP = 2.0;
|
26871
27714
|
var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
|
26872
27715
|
var SKIP_BUFFER_RANGE_START = 0.05;
|
26873
|
-
var GapController = /*#__PURE__*/function () {
|
27716
|
+
var GapController = /*#__PURE__*/function (_Logger) {
|
27717
|
+
_inheritsLoose(GapController, _Logger);
|
26874
27718
|
function GapController(config, media, fragmentTracker, hls) {
|
26875
|
-
|
26876
|
-
this.
|
26877
|
-
|
26878
|
-
|
26879
|
-
|
26880
|
-
|
26881
|
-
|
26882
|
-
|
26883
|
-
|
26884
|
-
|
26885
|
-
|
26886
|
-
|
26887
|
-
|
27719
|
+
var _this;
|
27720
|
+
_this = _Logger.call(this, 'gap-controller', hls.logger) || this;
|
27721
|
+
_this.config = void 0;
|
27722
|
+
_this.media = null;
|
27723
|
+
_this.fragmentTracker = void 0;
|
27724
|
+
_this.hls = void 0;
|
27725
|
+
_this.nudgeRetry = 0;
|
27726
|
+
_this.stallReported = false;
|
27727
|
+
_this.stalled = null;
|
27728
|
+
_this.moved = false;
|
27729
|
+
_this.seeking = false;
|
27730
|
+
_this.ended = 0;
|
27731
|
+
_this.config = config;
|
27732
|
+
_this.media = media;
|
27733
|
+
_this.fragmentTracker = fragmentTracker;
|
27734
|
+
_this.hls = hls;
|
27735
|
+
return _this;
|
26888
27736
|
}
|
26889
27737
|
var _proto = GapController.prototype;
|
26890
27738
|
_proto.destroy = function destroy() {
|
@@ -26899,7 +27747,7 @@
|
|
26899
27747
|
*
|
26900
27748
|
* @param lastCurrentTime - Previously read playhead position
|
26901
27749
|
*/;
|
26902
|
-
_proto.poll = function poll(lastCurrentTime, activeFrag) {
|
27750
|
+
_proto.poll = function poll(lastCurrentTime, activeFrag, levelDetails, state) {
|
26903
27751
|
var config = this.config,
|
26904
27752
|
media = this.media,
|
26905
27753
|
stalled = this.stalled;
|
@@ -26914,6 +27762,7 @@
|
|
26914
27762
|
|
26915
27763
|
// The playhead is moving, no-op
|
26916
27764
|
if (currentTime !== lastCurrentTime) {
|
27765
|
+
this.ended = 0;
|
26917
27766
|
this.moved = true;
|
26918
27767
|
if (!seeking) {
|
26919
27768
|
this.nudgeRetry = 0;
|
@@ -26922,7 +27771,7 @@
|
|
26922
27771
|
// The playhead is now moving, but was previously stalled
|
26923
27772
|
if (this.stallReported) {
|
26924
27773
|
var _stalledDuration = self.performance.now() - stalled;
|
26925
|
-
|
27774
|
+
this.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
|
26926
27775
|
this.stallReported = false;
|
26927
27776
|
}
|
26928
27777
|
this.stalled = null;
|
@@ -26958,7 +27807,6 @@
|
|
26958
27807
|
// Skip start gaps if we haven't played, but the last poll detected the start of a stall
|
26959
27808
|
// The addition poll gives the browser a chance to jump the gap for us
|
26960
27809
|
if (!this.moved && this.stalled !== null) {
|
26961
|
-
var _level$details;
|
26962
27810
|
// There is no playable buffer (seeked, waiting for buffer)
|
26963
27811
|
var isBuffered = bufferInfo.len > 0;
|
26964
27812
|
if (!isBuffered && !nextStart) {
|
@@ -26970,9 +27818,8 @@
|
|
26970
27818
|
// When joining a live stream with audio tracks, account for live playlist window sliding by allowing
|
26971
27819
|
// a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
|
26972
27820
|
// that begins over 1 target duration after the video start position.
|
26973
|
-
var
|
26974
|
-
var
|
26975
|
-
var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP;
|
27821
|
+
var isLive = !!(levelDetails != null && levelDetails.live);
|
27822
|
+
var maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
|
26976
27823
|
var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
|
26977
27824
|
if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
|
26978
27825
|
if (!media.paused) {
|
@@ -26990,6 +27837,17 @@
|
|
26990
27837
|
}
|
26991
27838
|
var stalledDuration = tnow - stalled;
|
26992
27839
|
if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
|
27840
|
+
// Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
|
27841
|
+
if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
|
27842
|
+
if (stalledDuration < 1000 || this.ended) {
|
27843
|
+
return;
|
27844
|
+
}
|
27845
|
+
this.ended = currentTime;
|
27846
|
+
this.hls.trigger(Events.MEDIA_ENDED, {
|
27847
|
+
stalled: true
|
27848
|
+
});
|
27849
|
+
return;
|
27850
|
+
}
|
26993
27851
|
// Report stalling after trying to fix
|
26994
27852
|
this._reportStall(bufferInfo);
|
26995
27853
|
if (!this.media) {
|
@@ -27031,7 +27889,7 @@
|
|
27031
27889
|
// needs to cross some sort of threshold covering all source-buffers content
|
27032
27890
|
// to start playing properly.
|
27033
27891
|
if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
|
27034
|
-
|
27892
|
+
this.warn('Trying to nudge playhead over buffer-hole');
|
27035
27893
|
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
|
27036
27894
|
// We only try to jump the hole if it's under the configured size
|
27037
27895
|
// Reset stalled so to rearm watchdog timer
|
@@ -27053,7 +27911,7 @@
|
|
27053
27911
|
// Report stalled error once
|
27054
27912
|
this.stallReported = true;
|
27055
27913
|
var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
|
27056
|
-
|
27914
|
+
this.warn(error.message);
|
27057
27915
|
hls.trigger(Events.ERROR, {
|
27058
27916
|
type: ErrorTypes.MEDIA_ERROR,
|
27059
27917
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27117,7 +27975,7 @@
|
|
27117
27975
|
}
|
27118
27976
|
}
|
27119
27977
|
var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
|
27120
|
-
|
27978
|
+
this.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
|
27121
27979
|
this.moved = true;
|
27122
27980
|
this.stalled = null;
|
27123
27981
|
media.currentTime = targetTime;
|
@@ -27156,7 +28014,7 @@
|
|
27156
28014
|
var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
|
27157
28015
|
// playback stalled in buffered area ... let's nudge currentTime to try to overcome this
|
27158
28016
|
var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
|
27159
|
-
|
28017
|
+
this.warn(error.message);
|
27160
28018
|
media.currentTime = targetTime;
|
27161
28019
|
hls.trigger(Events.ERROR, {
|
27162
28020
|
type: ErrorTypes.MEDIA_ERROR,
|
@@ -27166,7 +28024,7 @@
|
|
27166
28024
|
});
|
27167
28025
|
} else {
|
27168
28026
|
var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
|
27169
|
-
|
28027
|
+
this.error(_error.message);
|
27170
28028
|
hls.trigger(Events.ERROR, {
|
27171
28029
|
type: ErrorTypes.MEDIA_ERROR,
|
27172
28030
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -27176,14 +28034,14 @@
|
|
27176
28034
|
}
|
27177
28035
|
};
|
27178
28036
|
return GapController;
|
27179
|
-
}();
|
28037
|
+
}(Logger);
|
27180
28038
|
|
27181
28039
|
var TICK_INTERVAL = 100; // how often to tick in ms
|
27182
28040
|
var StreamController = /*#__PURE__*/function (_BaseStreamController) {
|
27183
28041
|
_inheritsLoose(StreamController, _BaseStreamController);
|
27184
28042
|
function StreamController(hls, fragmentTracker, keyLoader) {
|
27185
28043
|
var _this;
|
27186
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '
|
28044
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
|
27187
28045
|
_this.audioCodecSwap = false;
|
27188
28046
|
_this.gapController = null;
|
27189
28047
|
_this.level = -1;
|
@@ -27191,27 +28049,43 @@
|
|
27191
28049
|
_this.altAudio = false;
|
27192
28050
|
_this.audioOnly = false;
|
27193
28051
|
_this.fragPlaying = null;
|
27194
|
-
_this.onvplaying = null;
|
27195
|
-
_this.onvseeked = null;
|
27196
28052
|
_this.fragLastKbps = 0;
|
27197
28053
|
_this.couldBacktrack = false;
|
27198
28054
|
_this.backtrackFragment = null;
|
27199
28055
|
_this.audioCodecSwitch = false;
|
27200
28056
|
_this.videoBuffer = null;
|
27201
|
-
_this.
|
28057
|
+
_this.onMediaPlaying = function () {
|
28058
|
+
// tick to speed up FRAG_CHANGED triggering
|
28059
|
+
_this.tick();
|
28060
|
+
};
|
28061
|
+
_this.onMediaSeeked = function () {
|
28062
|
+
var media = _this.media;
|
28063
|
+
var currentTime = media ? media.currentTime : null;
|
28064
|
+
if (isFiniteNumber(currentTime)) {
|
28065
|
+
_this.log("Media seeked to " + currentTime.toFixed(3));
|
28066
|
+
}
|
28067
|
+
|
28068
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
28069
|
+
var bufferInfo = _this.getMainFwdBufferInfo();
|
28070
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
28071
|
+
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
28072
|
+
return;
|
28073
|
+
}
|
28074
|
+
|
28075
|
+
// tick to speed up FRAG_CHANGED triggering
|
28076
|
+
_this.tick();
|
28077
|
+
};
|
28078
|
+
_this.registerListeners();
|
27202
28079
|
return _this;
|
27203
28080
|
}
|
27204
28081
|
var _proto = StreamController.prototype;
|
27205
|
-
_proto.
|
28082
|
+
_proto.registerListeners = function registerListeners() {
|
28083
|
+
_BaseStreamController.prototype.registerListeners.call(this);
|
27206
28084
|
var hls = this.hls;
|
27207
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27208
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27209
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
27210
28085
|
hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27211
28086
|
hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
|
27212
28087
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27213
28088
|
hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27214
|
-
hls.on(Events.ERROR, this.onError, this);
|
27215
28089
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27216
28090
|
hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27217
28091
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27219,15 +28093,12 @@
|
|
27219
28093
|
hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
|
27220
28094
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27221
28095
|
};
|
27222
|
-
_proto.
|
28096
|
+
_proto.unregisterListeners = function unregisterListeners() {
|
28097
|
+
_BaseStreamController.prototype.unregisterListeners.call(this);
|
27223
28098
|
var hls = this.hls;
|
27224
|
-
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27225
|
-
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27226
|
-
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
27227
28099
|
hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
27228
28100
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
27229
28101
|
hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27230
|
-
hls.off(Events.ERROR, this.onError, this);
|
27231
28102
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
27232
28103
|
hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
27233
28104
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -27236,7 +28107,9 @@
|
|
27236
28107
|
hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
27237
28108
|
};
|
27238
28109
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
27239
|
-
|
28110
|
+
// @ts-ignore
|
28111
|
+
this.onMediaPlaying = this.onMediaSeeked = null;
|
28112
|
+
this.unregisterListeners();
|
27240
28113
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
27241
28114
|
};
|
27242
28115
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -27260,7 +28133,8 @@
|
|
27260
28133
|
}
|
27261
28134
|
// set new level to playlist loader : this will trigger start level load
|
27262
28135
|
// hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded
|
27263
|
-
|
28136
|
+
hls.nextLoadLevel = startLevel;
|
28137
|
+
this.level = hls.loadLevel;
|
27264
28138
|
this.loadedmetadata = false;
|
27265
28139
|
}
|
27266
28140
|
// if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime
|
@@ -27345,7 +28219,7 @@
|
|
27345
28219
|
if (this.altAudio && this.audioOnly) {
|
27346
28220
|
return;
|
27347
28221
|
}
|
27348
|
-
if (!(levels != null && levels[level])) {
|
28222
|
+
if (!this.buffering || !(levels != null && levels[level])) {
|
27349
28223
|
return;
|
27350
28224
|
}
|
27351
28225
|
var levelInfo = levels[level];
|
@@ -27551,18 +28425,15 @@
|
|
27551
28425
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
27552
28426
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
27553
28427
|
var media = data.media;
|
27554
|
-
|
27555
|
-
|
27556
|
-
media.addEventListener('playing', this.onvplaying);
|
27557
|
-
media.addEventListener('seeked', this.onvseeked);
|
28428
|
+
media.addEventListener('playing', this.onMediaPlaying);
|
28429
|
+
media.addEventListener('seeked', this.onMediaSeeked);
|
27558
28430
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
27559
28431
|
};
|
27560
28432
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
27561
28433
|
var media = this.media;
|
27562
|
-
if (media
|
27563
|
-
media.removeEventListener('playing', this.
|
27564
|
-
media.removeEventListener('seeked', this.
|
27565
|
-
this.onvplaying = this.onvseeked = null;
|
28434
|
+
if (media) {
|
28435
|
+
media.removeEventListener('playing', this.onMediaPlaying);
|
28436
|
+
media.removeEventListener('seeked', this.onMediaSeeked);
|
27566
28437
|
this.videoBuffer = null;
|
27567
28438
|
}
|
27568
28439
|
this.fragPlaying = null;
|
@@ -27572,27 +28443,6 @@
|
|
27572
28443
|
}
|
27573
28444
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
27574
28445
|
};
|
27575
|
-
_proto.onMediaPlaying = function onMediaPlaying() {
|
27576
|
-
// tick to speed up FRAG_CHANGED triggering
|
27577
|
-
this.tick();
|
27578
|
-
};
|
27579
|
-
_proto.onMediaSeeked = function onMediaSeeked() {
|
27580
|
-
var media = this.media;
|
27581
|
-
var currentTime = media ? media.currentTime : null;
|
27582
|
-
if (isFiniteNumber(currentTime)) {
|
27583
|
-
this.log("Media seeked to " + currentTime.toFixed(3));
|
27584
|
-
}
|
27585
|
-
|
27586
|
-
// If seeked was issued before buffer was appended do not tick immediately
|
27587
|
-
var bufferInfo = this.getMainFwdBufferInfo();
|
27588
|
-
if (bufferInfo === null || bufferInfo.len === 0) {
|
27589
|
-
this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27590
|
-
return;
|
27591
|
-
}
|
27592
|
-
|
27593
|
-
// tick to speed up FRAG_CHANGED triggering
|
27594
|
-
this.tick();
|
27595
|
-
};
|
27596
28446
|
_proto.onManifestLoading = function onManifestLoading() {
|
27597
28447
|
// reset buffer on manifest loading
|
27598
28448
|
this.log('Trigger BUFFER_RESET');
|
@@ -27873,8 +28723,10 @@
|
|
27873
28723
|
}
|
27874
28724
|
if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
|
27875
28725
|
// Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
|
27876
|
-
var
|
27877
|
-
|
28726
|
+
var state = this.state;
|
28727
|
+
var activeFrag = state !== State.IDLE ? this.fragCurrent : null;
|
28728
|
+
var levelDetails = this.getLevelDetails();
|
28729
|
+
gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
|
27878
28730
|
}
|
27879
28731
|
this.lastCurrentTime = media.currentTime;
|
27880
28732
|
};
|
@@ -28339,9 +29191,12 @@
|
|
28339
29191
|
* The configuration object provided on player instantiation.
|
28340
29192
|
*/
|
28341
29193
|
this.userConfig = void 0;
|
29194
|
+
/**
|
29195
|
+
* The logger functions used by this player instance, configured on player instantiation.
|
29196
|
+
*/
|
29197
|
+
this.logger = void 0;
|
28342
29198
|
this.coreComponents = void 0;
|
28343
29199
|
this.networkControllers = void 0;
|
28344
|
-
this.started = false;
|
28345
29200
|
this._emitter = new EventEmitter();
|
28346
29201
|
this._autoLevelCapping = -1;
|
28347
29202
|
this._maxHdcpLevel = null;
|
@@ -28358,11 +29213,11 @@
|
|
28358
29213
|
this._media = null;
|
28359
29214
|
this.url = null;
|
28360
29215
|
this.triggeringException = void 0;
|
28361
|
-
enableLogs(userConfig.debug || false, 'Hls instance');
|
28362
|
-
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
|
29216
|
+
var logger = this.logger = enableLogs(userConfig.debug || false, 'Hls instance');
|
29217
|
+
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig, logger);
|
28363
29218
|
this.userConfig = userConfig;
|
28364
29219
|
if (config.progressive) {
|
28365
|
-
enableStreamingMode(config);
|
29220
|
+
enableStreamingMode(config, logger);
|
28366
29221
|
}
|
28367
29222
|
|
28368
29223
|
// core controllers and network loaders
|
@@ -28470,7 +29325,7 @@
|
|
28470
29325
|
try {
|
28471
29326
|
return this.emit(event, event, eventObject);
|
28472
29327
|
} catch (error) {
|
28473
|
-
logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
29328
|
+
this.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
28474
29329
|
// Prevent recursion in error event handlers that throw #5497
|
28475
29330
|
if (!this.triggeringException) {
|
28476
29331
|
this.triggeringException = true;
|
@@ -28496,7 +29351,7 @@
|
|
28496
29351
|
* Dispose of the instance
|
28497
29352
|
*/;
|
28498
29353
|
_proto.destroy = function destroy() {
|
28499
|
-
logger.log('destroy');
|
29354
|
+
this.logger.log('destroy');
|
28500
29355
|
this.trigger(Events.DESTROYING, undefined);
|
28501
29356
|
this.detachMedia();
|
28502
29357
|
this.removeAllListeners();
|
@@ -28521,7 +29376,7 @@
|
|
28521
29376
|
* Attaches Hls.js to a media element
|
28522
29377
|
*/;
|
28523
29378
|
_proto.attachMedia = function attachMedia(media) {
|
28524
|
-
logger.log('attachMedia');
|
29379
|
+
this.logger.log('attachMedia');
|
28525
29380
|
this._media = media;
|
28526
29381
|
this.trigger(Events.MEDIA_ATTACHING, {
|
28527
29382
|
media: media
|
@@ -28532,7 +29387,7 @@
|
|
28532
29387
|
* Detach Hls.js from the media
|
28533
29388
|
*/;
|
28534
29389
|
_proto.detachMedia = function detachMedia() {
|
28535
|
-
logger.log('detachMedia');
|
29390
|
+
this.logger.log('detachMedia');
|
28536
29391
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
28537
29392
|
this._media = null;
|
28538
29393
|
}
|
@@ -28549,7 +29404,7 @@
|
|
28549
29404
|
});
|
28550
29405
|
this._autoLevelCapping = -1;
|
28551
29406
|
this._maxHdcpLevel = null;
|
28552
|
-
logger.log("loadSource:" + loadingSource);
|
29407
|
+
this.logger.log("loadSource:" + loadingSource);
|
28553
29408
|
if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
|
28554
29409
|
this.detachMedia();
|
28555
29410
|
this.attachMedia(media);
|
@@ -28571,8 +29426,7 @@
|
|
28571
29426
|
if (startPosition === void 0) {
|
28572
29427
|
startPosition = -1;
|
28573
29428
|
}
|
28574
|
-
logger.log("startLoad(" + startPosition + ")");
|
28575
|
-
this.started = true;
|
29429
|
+
this.logger.log("startLoad(" + startPosition + ")");
|
28576
29430
|
this.networkControllers.forEach(function (controller) {
|
28577
29431
|
controller.startLoad(startPosition);
|
28578
29432
|
});
|
@@ -28582,34 +29436,31 @@
|
|
28582
29436
|
* Stop loading of any stream data.
|
28583
29437
|
*/;
|
28584
29438
|
_proto.stopLoad = function stopLoad() {
|
28585
|
-
logger.log('stopLoad');
|
28586
|
-
this.started = false;
|
29439
|
+
this.logger.log('stopLoad');
|
28587
29440
|
this.networkControllers.forEach(function (controller) {
|
28588
29441
|
controller.stopLoad();
|
28589
29442
|
});
|
28590
29443
|
}
|
28591
29444
|
|
28592
29445
|
/**
|
28593
|
-
* Resumes stream controller segment loading
|
29446
|
+
* Resumes stream controller segment loading after `pauseBuffering` has been called.
|
28594
29447
|
*/;
|
28595
29448
|
_proto.resumeBuffering = function resumeBuffering() {
|
28596
|
-
|
28597
|
-
|
28598
|
-
|
28599
|
-
|
28600
|
-
|
28601
|
-
});
|
28602
|
-
}
|
29449
|
+
this.networkControllers.forEach(function (controller) {
|
29450
|
+
if (controller.resumeBuffering) {
|
29451
|
+
controller.resumeBuffering();
|
29452
|
+
}
|
29453
|
+
});
|
28603
29454
|
}
|
28604
29455
|
|
28605
29456
|
/**
|
28606
|
-
*
|
29457
|
+
* Prevents stream controller from loading new segments until `resumeBuffering` is called.
|
28607
29458
|
* This allows for media buffering to be paused without interupting playlist loading.
|
28608
29459
|
*/;
|
28609
29460
|
_proto.pauseBuffering = function pauseBuffering() {
|
28610
29461
|
this.networkControllers.forEach(function (controller) {
|
28611
|
-
if (
|
28612
|
-
controller.
|
29462
|
+
if (controller.pauseBuffering) {
|
29463
|
+
controller.pauseBuffering();
|
28613
29464
|
}
|
28614
29465
|
});
|
28615
29466
|
}
|
@@ -28618,7 +29469,7 @@
|
|
28618
29469
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
28619
29470
|
*/;
|
28620
29471
|
_proto.swapAudioCodec = function swapAudioCodec() {
|
28621
|
-
logger.log('swapAudioCodec');
|
29472
|
+
this.logger.log('swapAudioCodec');
|
28622
29473
|
this.streamController.swapAudioCodec();
|
28623
29474
|
}
|
28624
29475
|
|
@@ -28629,7 +29480,7 @@
|
|
28629
29480
|
* Automatic recovery of media-errors by this process is configurable.
|
28630
29481
|
*/;
|
28631
29482
|
_proto.recoverMediaError = function recoverMediaError() {
|
28632
|
-
logger.log('recoverMediaError');
|
29483
|
+
this.logger.log('recoverMediaError');
|
28633
29484
|
var media = this._media;
|
28634
29485
|
this.detachMedia();
|
28635
29486
|
if (media) {
|
@@ -28684,7 +29535,7 @@
|
|
28684
29535
|
* Set quality level index immediately. This will flush the current buffer to replace the quality asap. That means playback will interrupt at least shortly to re-buffer and re-sync eventually. Set to -1 for automatic level selection.
|
28685
29536
|
*/,
|
28686
29537
|
set: function set(newLevel) {
|
28687
|
-
logger.log("set currentLevel:" + newLevel);
|
29538
|
+
this.logger.log("set currentLevel:" + newLevel);
|
28688
29539
|
this.levelController.manualLevel = newLevel;
|
28689
29540
|
this.streamController.immediateLevelSwitch();
|
28690
29541
|
}
|
@@ -28705,7 +29556,7 @@
|
|
28705
29556
|
* @param newLevel - Pass -1 for automatic level selection
|
28706
29557
|
*/,
|
28707
29558
|
set: function set(newLevel) {
|
28708
|
-
logger.log("set nextLevel:" + newLevel);
|
29559
|
+
this.logger.log("set nextLevel:" + newLevel);
|
28709
29560
|
this.levelController.manualLevel = newLevel;
|
28710
29561
|
this.streamController.nextLevelSwitch();
|
28711
29562
|
}
|
@@ -28726,7 +29577,7 @@
|
|
28726
29577
|
* @param newLevel - Pass -1 for automatic level selection
|
28727
29578
|
*/,
|
28728
29579
|
set: function set(newLevel) {
|
28729
|
-
logger.log("set loadLevel:" + newLevel);
|
29580
|
+
this.logger.log("set loadLevel:" + newLevel);
|
28730
29581
|
this.levelController.manualLevel = newLevel;
|
28731
29582
|
}
|
28732
29583
|
|
@@ -28761,7 +29612,7 @@
|
|
28761
29612
|
* Sets "first-level", see getter.
|
28762
29613
|
*/,
|
28763
29614
|
set: function set(newLevel) {
|
28764
|
-
logger.log("set firstLevel:" + newLevel);
|
29615
|
+
this.logger.log("set firstLevel:" + newLevel);
|
28765
29616
|
this.levelController.firstLevel = newLevel;
|
28766
29617
|
}
|
28767
29618
|
|
@@ -28788,7 +29639,7 @@
|
|
28788
29639
|
* (determined from download of first segment)
|
28789
29640
|
*/,
|
28790
29641
|
set: function set(newLevel) {
|
28791
|
-
logger.log("set startLevel:" + newLevel);
|
29642
|
+
this.logger.log("set startLevel:" + newLevel);
|
28792
29643
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
28793
29644
|
if (newLevel !== -1) {
|
28794
29645
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -28841,7 +29692,7 @@
|
|
28841
29692
|
*/
|
28842
29693
|
function set(newLevel) {
|
28843
29694
|
if (this._autoLevelCapping !== newLevel) {
|
28844
|
-
logger.log("set autoLevelCapping:" + newLevel);
|
29695
|
+
this.logger.log("set autoLevelCapping:" + newLevel);
|
28845
29696
|
this._autoLevelCapping = newLevel;
|
28846
29697
|
this.levelController.checkMaxAutoUpdated();
|
28847
29698
|
}
|
@@ -29166,7 +30017,7 @@
|
|
29166
30017
|
* Get the video-dev/hls.js package version.
|
29167
30018
|
*/
|
29168
30019
|
function get() {
|
29169
|
-
return "1.5.
|
30020
|
+
return "1.5.5-0.canary.9977";
|
29170
30021
|
}
|
29171
30022
|
}, {
|
29172
30023
|
key: "Events",
|