hls.js 1.5.6-0.canary.10011 → 1.5.6
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 +0 -1
- package/dist/hls-demo.js +0 -10
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +1134 -2043
- package/dist/hls.js.d.ts +50 -65
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +852 -1141
- 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 +686 -974
- 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 +847 -1741
- 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 +21 -21
- package/src/config.ts +2 -3
- package/src/controller/abr-controller.ts +20 -21
- package/src/controller/audio-stream-controller.ts +16 -15
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +8 -20
- package/src/controller/base-stream-controller.ts +33 -149
- package/src/controller/buffer-controller.ts +11 -11
- package/src/controller/cap-level-controller.ts +2 -1
- package/src/controller/cmcd-controller.ts +6 -27
- package/src/controller/content-steering-controller.ts +6 -8
- package/src/controller/eme-controller.ts +22 -9
- package/src/controller/error-controller.ts +8 -6
- package/src/controller/fps-controller.ts +3 -2
- package/src/controller/gap-controller.ts +16 -43
- package/src/controller/latency-controller.ts +11 -9
- package/src/controller/level-controller.ts +18 -12
- package/src/controller/stream-controller.ts +32 -25
- package/src/controller/subtitle-stream-controller.ts +14 -13
- package/src/controller/subtitle-track-controller.ts +3 -5
- package/src/controller/timeline-controller.ts +30 -23
- package/src/crypt/aes-crypto.ts +2 -21
- package/src/crypt/decrypter.ts +18 -32
- package/src/crypt/fast-aes-key.ts +5 -24
- package/src/demux/audio/adts.ts +4 -9
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +12 -4
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +3 -16
- package/src/demux/tsdemuxer.ts +37 -71
- package/src/demux/video/avc-video-parser.ts +119 -208
- package/src/demux/video/base-video-parser.ts +2 -134
- package/src/demux/video/exp-golomb.ts +208 -0
- package/src/events.ts +0 -7
- package/src/hls.ts +34 -42
- package/src/loader/fragment-loader.ts +2 -9
- package/src/loader/key-loader.ts +0 -2
- package/src/loader/level-key.ts +9 -10
- package/src/loader/playlist-loader.ts +5 -4
- package/src/remux/mp4-generator.ts +1 -196
- package/src/remux/mp4-remuxer.ts +7 -23
- package/src/task-loop.ts +2 -5
- package/src/types/component-api.ts +0 -2
- package/src/types/demuxer.ts +0 -3
- package/src/types/events.ts +0 -4
- package/src/utils/codecs.ts +4 -33
- package/src/utils/logger.ts +24 -54
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/demux/video/hevc-video-parser.ts +0 -746
- package/src/utils/encryption-methods-util.ts +0 -21
package/dist/hls.js
CHANGED
@@ -5,21 +5,6 @@
|
|
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
|
-
}
|
23
8
|
function ownKeys(e, r) {
|
24
9
|
var t = Object.keys(e);
|
25
10
|
if (Object.getOwnPropertySymbols) {
|
@@ -118,6 +103,32 @@
|
|
118
103
|
};
|
119
104
|
return _setPrototypeOf(o, p);
|
120
105
|
}
|
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
|
+
}
|
121
132
|
function _isNativeFunction(fn) {
|
122
133
|
try {
|
123
134
|
return Function.toString.call(fn).indexOf("[native code]") !== -1;
|
@@ -383,7 +394,6 @@
|
|
383
394
|
Events["MEDIA_ATTACHED"] = "hlsMediaAttached";
|
384
395
|
Events["MEDIA_DETACHING"] = "hlsMediaDetaching";
|
385
396
|
Events["MEDIA_DETACHED"] = "hlsMediaDetached";
|
386
|
-
Events["MEDIA_ENDED"] = "hlsMediaEnded";
|
387
397
|
Events["BUFFER_RESET"] = "hlsBufferReset";
|
388
398
|
Events["BUFFER_CODECS"] = "hlsBufferCodecs";
|
389
399
|
Events["BUFFER_CREATED"] = "hlsBufferCreated";
|
@@ -497,6 +507,61 @@
|
|
497
507
|
return ErrorDetails;
|
498
508
|
}({});
|
499
509
|
|
510
|
+
var noop = function noop() {};
|
511
|
+
var fakeLogger = {
|
512
|
+
trace: noop,
|
513
|
+
debug: noop,
|
514
|
+
log: noop,
|
515
|
+
warn: noop,
|
516
|
+
info: noop,
|
517
|
+
error: noop
|
518
|
+
};
|
519
|
+
var exportedLogger = fakeLogger;
|
520
|
+
|
521
|
+
// let lastCallTime;
|
522
|
+
// function formatMsgWithTimeInfo(type, msg) {
|
523
|
+
// const now = Date.now();
|
524
|
+
// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
|
525
|
+
// lastCallTime = now;
|
526
|
+
// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
|
527
|
+
// return msg;
|
528
|
+
// }
|
529
|
+
|
530
|
+
function consolePrintFn(type) {
|
531
|
+
var func = self.console[type];
|
532
|
+
if (func) {
|
533
|
+
return func.bind(self.console, "[" + type + "] >");
|
534
|
+
}
|
535
|
+
return noop;
|
536
|
+
}
|
537
|
+
function exportLoggerFunctions(debugConfig) {
|
538
|
+
for (var _len = arguments.length, functions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
539
|
+
functions[_key - 1] = arguments[_key];
|
540
|
+
}
|
541
|
+
functions.forEach(function (type) {
|
542
|
+
exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);
|
543
|
+
});
|
544
|
+
}
|
545
|
+
function enableLogs(debugConfig, id) {
|
546
|
+
// check that console is available
|
547
|
+
if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
|
548
|
+
exportLoggerFunctions(debugConfig,
|
549
|
+
// Remove out from list here to hard-disable a log-level
|
550
|
+
// 'trace',
|
551
|
+
'debug', 'log', 'info', 'warn', 'error');
|
552
|
+
// Some browsers don't allow to use bind on console object anyway
|
553
|
+
// fallback to default if needed
|
554
|
+
try {
|
555
|
+
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.6");
|
556
|
+
} catch (e) {
|
557
|
+
exportedLogger = fakeLogger;
|
558
|
+
}
|
559
|
+
} else {
|
560
|
+
exportedLogger = fakeLogger;
|
561
|
+
}
|
562
|
+
}
|
563
|
+
var logger = exportedLogger;
|
564
|
+
|
500
565
|
var DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/;
|
501
566
|
var ATTR_LIST_REGEX = /(.+?)=(".*?"|.*?)(?:,|$)/g;
|
502
567
|
|
@@ -585,77 +650,6 @@
|
|
585
650
|
return AttrList;
|
586
651
|
}();
|
587
652
|
|
588
|
-
var Logger = function Logger(label, logger) {
|
589
|
-
this.trace = void 0;
|
590
|
-
this.debug = void 0;
|
591
|
-
this.log = void 0;
|
592
|
-
this.warn = void 0;
|
593
|
-
this.info = void 0;
|
594
|
-
this.error = void 0;
|
595
|
-
var lb = "[" + label + "]:";
|
596
|
-
this.trace = noop;
|
597
|
-
this.debug = logger.debug.bind(null, lb);
|
598
|
-
this.log = logger.log.bind(null, lb);
|
599
|
-
this.warn = logger.warn.bind(null, lb);
|
600
|
-
this.info = logger.info.bind(null, lb);
|
601
|
-
this.error = logger.error.bind(null, lb);
|
602
|
-
};
|
603
|
-
var noop = function noop() {};
|
604
|
-
var fakeLogger = {
|
605
|
-
trace: noop,
|
606
|
-
debug: noop,
|
607
|
-
log: noop,
|
608
|
-
warn: noop,
|
609
|
-
info: noop,
|
610
|
-
error: noop
|
611
|
-
};
|
612
|
-
function createLogger() {
|
613
|
-
return _extends({}, fakeLogger);
|
614
|
-
}
|
615
|
-
|
616
|
-
// let lastCallTime;
|
617
|
-
// function formatMsgWithTimeInfo(type, msg) {
|
618
|
-
// const now = Date.now();
|
619
|
-
// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
|
620
|
-
// lastCallTime = now;
|
621
|
-
// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
|
622
|
-
// return msg;
|
623
|
-
// }
|
624
|
-
|
625
|
-
function consolePrintFn(type, id) {
|
626
|
-
var func = self.console[type];
|
627
|
-
return func ? func.bind(self.console, (id ? '[' + id + '] ' : '') + "[" + type + "] >") : noop;
|
628
|
-
}
|
629
|
-
function getLoggerFn(key, debugConfig, id) {
|
630
|
-
return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key, id);
|
631
|
-
}
|
632
|
-
var exportedLogger = createLogger();
|
633
|
-
function enableLogs(debugConfig, context, id) {
|
634
|
-
// check that console is available
|
635
|
-
var newLogger = createLogger();
|
636
|
-
if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
|
637
|
-
var keys = [
|
638
|
-
// Remove out from list here to hard-disable a log-level
|
639
|
-
// 'trace',
|
640
|
-
'debug', 'log', 'info', 'warn', 'error'];
|
641
|
-
keys.forEach(function (key) {
|
642
|
-
newLogger[key] = getLoggerFn(key, debugConfig, id);
|
643
|
-
});
|
644
|
-
// Some browsers don't allow to use bind on console object anyway
|
645
|
-
// fallback to default if needed
|
646
|
-
try {
|
647
|
-
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.6-0.canary.10011");
|
648
|
-
} catch (e) {
|
649
|
-
/* log fn threw an exception. All logger methods are no-ops. */
|
650
|
-
return createLogger();
|
651
|
-
}
|
652
|
-
}
|
653
|
-
// global exported logger uses the log methods from last call to `enableLogs`
|
654
|
-
_extends(exportedLogger, newLogger);
|
655
|
-
return newLogger;
|
656
|
-
}
|
657
|
-
var logger = exportedLogger;
|
658
|
-
|
659
653
|
// Avoid exporting const enum so that these values can be inlined
|
660
654
|
|
661
655
|
function isDateRangeCueAttribute(attrName) {
|
@@ -1259,26 +1253,6 @@
|
|
1259
1253
|
});
|
1260
1254
|
}
|
1261
1255
|
|
1262
|
-
var DecrypterAesMode = {
|
1263
|
-
cbc: 0,
|
1264
|
-
ctr: 1
|
1265
|
-
};
|
1266
|
-
|
1267
|
-
function isFullSegmentEncryption(method) {
|
1268
|
-
return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
|
1269
|
-
}
|
1270
|
-
function getAesModeFromFullSegmentMethod(method) {
|
1271
|
-
switch (method) {
|
1272
|
-
case 'AES-128':
|
1273
|
-
case 'AES-256':
|
1274
|
-
return DecrypterAesMode.cbc;
|
1275
|
-
case 'AES-256-CTR':
|
1276
|
-
return DecrypterAesMode.ctr;
|
1277
|
-
default:
|
1278
|
-
throw new Error("invalid full segment method " + method);
|
1279
|
-
}
|
1280
|
-
}
|
1281
|
-
|
1282
1256
|
/** returns `undefined` is `self` is missing, e.g. in node */
|
1283
1257
|
var optionalSelf = typeof self !== 'undefined' ? self : undefined;
|
1284
1258
|
|
@@ -2951,13 +2925,13 @@
|
|
2951
2925
|
this.keyFormatVersions = formatversions;
|
2952
2926
|
this.iv = iv;
|
2953
2927
|
this.encrypted = method ? method !== 'NONE' : false;
|
2954
|
-
this.isCommonEncryption = this.encrypted &&
|
2928
|
+
this.isCommonEncryption = this.encrypted && method !== 'AES-128';
|
2955
2929
|
}
|
2956
2930
|
var _proto = LevelKey.prototype;
|
2957
2931
|
_proto.isSupported = function isSupported() {
|
2958
2932
|
// If it's Segment encryption or No encryption, just select that key system
|
2959
2933
|
if (this.method) {
|
2960
|
-
if (
|
2934
|
+
if (this.method === 'AES-128' || this.method === 'NONE') {
|
2961
2935
|
return true;
|
2962
2936
|
}
|
2963
2937
|
if (this.keyFormat === 'identity') {
|
@@ -2979,13 +2953,14 @@
|
|
2979
2953
|
if (!this.encrypted || !this.uri) {
|
2980
2954
|
return null;
|
2981
2955
|
}
|
2982
|
-
if (
|
2956
|
+
if (this.method === 'AES-128' && this.uri && !this.iv) {
|
2983
2957
|
if (typeof sn !== 'number') {
|
2984
2958
|
// We are fetching decryption data for a initialization segment
|
2985
|
-
// If the segment was encrypted with AES-128
|
2959
|
+
// If the segment was encrypted with AES-128
|
2986
2960
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
2987
|
-
|
2988
|
-
|
2961
|
+
if (this.method === 'AES-128' && !this.iv) {
|
2962
|
+
logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
|
2963
|
+
}
|
2989
2964
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
2990
2965
|
sn = 0;
|
2991
2966
|
}
|
@@ -3279,28 +3254,23 @@
|
|
3279
3254
|
if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
|
3280
3255
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
|
3281
3256
|
}
|
3257
|
+
|
3258
|
+
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3259
|
+
// some browsers will report that fLaC is supported then fail.
|
3260
|
+
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3282
3261
|
var codecsToCheck = {
|
3283
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3284
|
-
// some browsers will report that fLaC is supported then fail.
|
3285
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3286
3262
|
flac: ['flac', 'fLaC', 'FLAC'],
|
3287
|
-
opus: ['opus', 'Opus']
|
3288
|
-
// Replace audio codec info if browser does not support mp4a.40.34,
|
3289
|
-
// and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
|
3290
|
-
'mp4a.40.34': ['mp3']
|
3263
|
+
opus: ['opus', 'Opus']
|
3291
3264
|
}[lowerCaseCodec];
|
3292
3265
|
for (var i = 0; i < codecsToCheck.length; i++) {
|
3293
|
-
var _getMediaSource;
|
3294
3266
|
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
|
3295
3267
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
3296
3268
|
return codecsToCheck[i];
|
3297
|
-
} else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
|
3298
|
-
return '';
|
3299
3269
|
}
|
3300
3270
|
}
|
3301
3271
|
return lowerCaseCodec;
|
3302
3272
|
}
|
3303
|
-
var AUDIO_CODEC_REGEXP = /flac|opus
|
3273
|
+
var AUDIO_CODEC_REGEXP = /flac|opus/i;
|
3304
3274
|
function getCodecCompatibleName(codec, preferManagedMediaSource) {
|
3305
3275
|
if (preferManagedMediaSource === void 0) {
|
3306
3276
|
preferManagedMediaSource = true;
|
@@ -3328,18 +3298,6 @@
|
|
3328
3298
|
}
|
3329
3299
|
return codec;
|
3330
3300
|
}
|
3331
|
-
function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
|
3332
|
-
var MediaSource = getMediaSource(preferManagedMediaSource) || {
|
3333
|
-
isTypeSupported: function isTypeSupported() {
|
3334
|
-
return false;
|
3335
|
-
}
|
3336
|
-
};
|
3337
|
-
return {
|
3338
|
-
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
3339
|
-
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
3340
|
-
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
3341
|
-
};
|
3342
|
-
}
|
3343
3301
|
|
3344
3302
|
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;
|
3345
3303
|
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
|
@@ -4189,10 +4147,10 @@
|
|
4189
4147
|
var loaderContext = loader.context;
|
4190
4148
|
if (loaderContext && loaderContext.url === context.url && loaderContext.level === context.level) {
|
4191
4149
|
// same URL can't overlap
|
4192
|
-
|
4150
|
+
logger.trace('[playlist-loader]: playlist request ongoing');
|
4193
4151
|
return;
|
4194
4152
|
}
|
4195
|
-
|
4153
|
+
logger.log("[playlist-loader]: aborting previous loader for type: " + context.type);
|
4196
4154
|
loader.abort();
|
4197
4155
|
}
|
4198
4156
|
|
@@ -4302,7 +4260,7 @@
|
|
4302
4260
|
// alt audio rendition in which quality levels (main)
|
4303
4261
|
// contains both audio+video. but with mixed audio track not signaled
|
4304
4262
|
if (!embeddedAudioFound && levels[0].audioCodec && !levels[0].attrs.AUDIO) {
|
4305
|
-
|
4263
|
+
logger.log('[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one');
|
4306
4264
|
audioTracks.unshift({
|
4307
4265
|
type: 'main',
|
4308
4266
|
name: 'main',
|
@@ -4402,7 +4360,7 @@
|
|
4402
4360
|
message += " id: " + context.id + " group-id: \"" + context.groupId + "\"";
|
4403
4361
|
}
|
4404
4362
|
var error = new Error(message);
|
4405
|
-
|
4363
|
+
logger.warn("[playlist-loader]: " + message);
|
4406
4364
|
var details = ErrorDetails.UNKNOWN;
|
4407
4365
|
var fatal = false;
|
4408
4366
|
var loader = this.getInternalLoader(context);
|
@@ -5003,43 +4961,8 @@
|
|
5003
4961
|
this.currentTime = 0;
|
5004
4962
|
this.stallCount = 0;
|
5005
4963
|
this._latency = null;
|
5006
|
-
this.
|
5007
|
-
|
5008
|
-
levelDetails = _this.levelDetails;
|
5009
|
-
if (!media || !levelDetails) {
|
5010
|
-
return;
|
5011
|
-
}
|
5012
|
-
_this.currentTime = media.currentTime;
|
5013
|
-
var latency = _this.computeLatency();
|
5014
|
-
if (latency === null) {
|
5015
|
-
return;
|
5016
|
-
}
|
5017
|
-
_this._latency = latency;
|
5018
|
-
|
5019
|
-
// Adapt playbackRate to meet target latency in low-latency mode
|
5020
|
-
var _this$config = _this.config,
|
5021
|
-
lowLatencyMode = _this$config.lowLatencyMode,
|
5022
|
-
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5023
|
-
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5024
|
-
return;
|
5025
|
-
}
|
5026
|
-
var targetLatency = _this.targetLatency;
|
5027
|
-
if (targetLatency === null) {
|
5028
|
-
return;
|
5029
|
-
}
|
5030
|
-
var distanceFromTarget = latency - targetLatency;
|
5031
|
-
// Only adjust playbackRate when within one target duration of targetLatency
|
5032
|
-
// and more than one second from under-buffering.
|
5033
|
-
// Playback further than one target duration from target can be considered DVR playback.
|
5034
|
-
var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
|
5035
|
-
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5036
|
-
if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
|
5037
|
-
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5038
|
-
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
|
5039
|
-
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5040
|
-
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5041
|
-
media.playbackRate = 1;
|
5042
|
-
}
|
4964
|
+
this.timeupdateHandler = function () {
|
4965
|
+
return _this.timeupdate();
|
5043
4966
|
};
|
5044
4967
|
this.hls = hls;
|
5045
4968
|
this.config = hls.config;
|
@@ -5051,7 +4974,7 @@
|
|
5051
4974
|
this.onMediaDetaching();
|
5052
4975
|
this.levelDetails = null;
|
5053
4976
|
// @ts-ignore
|
5054
|
-
this.hls = null;
|
4977
|
+
this.hls = this.timeupdateHandler = null;
|
5055
4978
|
};
|
5056
4979
|
_proto.registerListeners = function registerListeners() {
|
5057
4980
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -5069,11 +4992,11 @@
|
|
5069
4992
|
};
|
5070
4993
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
5071
4994
|
this.media = data.media;
|
5072
|
-
this.media.addEventListener('timeupdate', this.
|
4995
|
+
this.media.addEventListener('timeupdate', this.timeupdateHandler);
|
5073
4996
|
};
|
5074
4997
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
5075
4998
|
if (this.media) {
|
5076
|
-
this.media.removeEventListener('timeupdate', this.
|
4999
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5077
5000
|
this.media = null;
|
5078
5001
|
}
|
5079
5002
|
};
|
@@ -5086,10 +5009,10 @@
|
|
5086
5009
|
var details = _ref.details;
|
5087
5010
|
this.levelDetails = details;
|
5088
5011
|
if (details.advanced) {
|
5089
|
-
this.
|
5012
|
+
this.timeupdate();
|
5090
5013
|
}
|
5091
5014
|
if (!details.live && this.media) {
|
5092
|
-
this.media.removeEventListener('timeupdate', this.
|
5015
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5093
5016
|
}
|
5094
5017
|
};
|
5095
5018
|
_proto.onError = function onError(event, data) {
|
@@ -5099,7 +5022,45 @@
|
|
5099
5022
|
}
|
5100
5023
|
this.stallCount++;
|
5101
5024
|
if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
|
5102
|
-
|
5025
|
+
logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
|
5026
|
+
}
|
5027
|
+
};
|
5028
|
+
_proto.timeupdate = function timeupdate() {
|
5029
|
+
var media = this.media,
|
5030
|
+
levelDetails = this.levelDetails;
|
5031
|
+
if (!media || !levelDetails) {
|
5032
|
+
return;
|
5033
|
+
}
|
5034
|
+
this.currentTime = media.currentTime;
|
5035
|
+
var latency = this.computeLatency();
|
5036
|
+
if (latency === null) {
|
5037
|
+
return;
|
5038
|
+
}
|
5039
|
+
this._latency = latency;
|
5040
|
+
|
5041
|
+
// Adapt playbackRate to meet target latency in low-latency mode
|
5042
|
+
var _this$config = this.config,
|
5043
|
+
lowLatencyMode = _this$config.lowLatencyMode,
|
5044
|
+
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5045
|
+
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5046
|
+
return;
|
5047
|
+
}
|
5048
|
+
var targetLatency = this.targetLatency;
|
5049
|
+
if (targetLatency === null) {
|
5050
|
+
return;
|
5051
|
+
}
|
5052
|
+
var distanceFromTarget = latency - targetLatency;
|
5053
|
+
// Only adjust playbackRate when within one target duration of targetLatency
|
5054
|
+
// and more than one second from under-buffering.
|
5055
|
+
// Playback further than one target duration from target can be considered DVR playback.
|
5056
|
+
var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
|
5057
|
+
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5058
|
+
if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
|
5059
|
+
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5060
|
+
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
|
5061
|
+
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5062
|
+
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5063
|
+
media.playbackRate = 1;
|
5103
5064
|
}
|
5104
5065
|
};
|
5105
5066
|
_proto.estimateLiveEdge = function estimateLiveEdge() {
|
@@ -6007,17 +5968,19 @@
|
|
6007
5968
|
MoveAllAlternatesMatchingHDCP: 2,
|
6008
5969
|
SwitchToSDR: 4
|
6009
5970
|
}; // Reserved for future use
|
6010
|
-
var ErrorController = /*#__PURE__*/function (
|
6011
|
-
_inheritsLoose(ErrorController, _Logger);
|
5971
|
+
var ErrorController = /*#__PURE__*/function () {
|
6012
5972
|
function ErrorController(hls) {
|
6013
|
-
|
6014
|
-
|
6015
|
-
|
6016
|
-
|
6017
|
-
|
6018
|
-
|
6019
|
-
|
6020
|
-
|
5973
|
+
this.hls = void 0;
|
5974
|
+
this.playlistError = 0;
|
5975
|
+
this.penalizedRenditions = {};
|
5976
|
+
this.log = void 0;
|
5977
|
+
this.warn = void 0;
|
5978
|
+
this.error = void 0;
|
5979
|
+
this.hls = hls;
|
5980
|
+
this.log = logger.log.bind(logger, "[info]:");
|
5981
|
+
this.warn = logger.warn.bind(logger, "[warning]:");
|
5982
|
+
this.error = logger.error.bind(logger, "[error]:");
|
5983
|
+
this.registerListeners();
|
6021
5984
|
}
|
6022
5985
|
var _proto = ErrorController.prototype;
|
6023
5986
|
_proto.registerListeners = function registerListeners() {
|
@@ -6373,19 +6336,19 @@
|
|
6373
6336
|
}
|
6374
6337
|
};
|
6375
6338
|
return ErrorController;
|
6376
|
-
}(
|
6339
|
+
}();
|
6377
6340
|
|
6378
|
-
var BasePlaylistController = /*#__PURE__*/function (
|
6379
|
-
_inheritsLoose(BasePlaylistController, _Logger);
|
6341
|
+
var BasePlaylistController = /*#__PURE__*/function () {
|
6380
6342
|
function BasePlaylistController(hls, logPrefix) {
|
6381
|
-
|
6382
|
-
|
6383
|
-
|
6384
|
-
|
6385
|
-
|
6386
|
-
|
6387
|
-
|
6388
|
-
|
6343
|
+
this.hls = void 0;
|
6344
|
+
this.timer = -1;
|
6345
|
+
this.requestScheduled = -1;
|
6346
|
+
this.canLoad = false;
|
6347
|
+
this.log = void 0;
|
6348
|
+
this.warn = void 0;
|
6349
|
+
this.log = logger.log.bind(logger, logPrefix + ":");
|
6350
|
+
this.warn = logger.warn.bind(logger, logPrefix + ":");
|
6351
|
+
this.hls = hls;
|
6389
6352
|
}
|
6390
6353
|
var _proto = BasePlaylistController.prototype;
|
6391
6354
|
_proto.destroy = function destroy() {
|
@@ -6418,7 +6381,7 @@
|
|
6418
6381
|
try {
|
6419
6382
|
uri = new self.URL(attr.URI, previous.url).href;
|
6420
6383
|
} catch (error) {
|
6421
|
-
|
6384
|
+
logger.warn("Could not construct new URL for Rendition Report: " + error);
|
6422
6385
|
uri = attr.URI || '';
|
6423
6386
|
}
|
6424
6387
|
// Use exact match. Otherwise, the last partial match, if any, will be used
|
@@ -6457,7 +6420,7 @@
|
|
6457
6420
|
return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
|
6458
6421
|
};
|
6459
6422
|
_proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
|
6460
|
-
var
|
6423
|
+
var _this = this;
|
6461
6424
|
var details = data.details,
|
6462
6425
|
stats = data.stats;
|
6463
6426
|
|
@@ -6504,12 +6467,7 @@
|
|
6504
6467
|
var cdnAge = lastAdvanced + details.ageHeader;
|
6505
6468
|
var currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5);
|
6506
6469
|
if (currentGoal > 0) {
|
6507
|
-
if (
|
6508
|
-
// Omit segment and part directives when the last response was more than 3 target durations ago,
|
6509
|
-
this.log("Playlist last advanced " + lastAdvanced.toFixed(2) + "s ago. Omitting segment and part directives.");
|
6510
|
-
msn = undefined;
|
6511
|
-
part = undefined;
|
6512
|
-
} else if (previousDetails != null && previousDetails.tuneInGoal && cdnAge - details.partTarget > previousDetails.tuneInGoal) {
|
6470
|
+
if (previousDetails && currentGoal > previousDetails.tuneInGoal) {
|
6513
6471
|
// If we attempted to get the next or latest playlist update, but currentGoal increased,
|
6514
6472
|
// then we either can't catchup, or the "age" header cannot be trusted.
|
6515
6473
|
this.warn("CDN Tune-in goal increased from: " + previousDetails.tuneInGoal + " to: " + currentGoal + " with playlist age: " + details.age);
|
@@ -6567,7 +6525,7 @@
|
|
6567
6525
|
// );
|
6568
6526
|
|
6569
6527
|
this.timer = self.setTimeout(function () {
|
6570
|
-
return
|
6528
|
+
return _this.loadPlaylist(deliveryDirectives);
|
6571
6529
|
}, estimatedTimeUntilUpdate);
|
6572
6530
|
} else {
|
6573
6531
|
this.clearTimer();
|
@@ -6583,7 +6541,7 @@
|
|
6583
6541
|
return new HlsUrlParameters(msn, part, skip);
|
6584
6542
|
};
|
6585
6543
|
_proto.checkRetry = function checkRetry(errorEvent) {
|
6586
|
-
var
|
6544
|
+
var _this2 = this;
|
6587
6545
|
var errorDetails = errorEvent.details;
|
6588
6546
|
var isTimeout = isTimeoutError(errorEvent);
|
6589
6547
|
var errorAction = errorEvent.errorAction;
|
@@ -6607,7 +6565,7 @@
|
|
6607
6565
|
var delay = getRetryDelay(retryConfig, retryCount);
|
6608
6566
|
// Schedule level/track reload
|
6609
6567
|
this.timer = self.setTimeout(function () {
|
6610
|
-
return
|
6568
|
+
return _this2.loadPlaylist();
|
6611
6569
|
}, delay);
|
6612
6570
|
this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
|
6613
6571
|
}
|
@@ -6618,7 +6576,7 @@
|
|
6618
6576
|
return retry;
|
6619
6577
|
};
|
6620
6578
|
return BasePlaylistController;
|
6621
|
-
}(
|
6579
|
+
}();
|
6622
6580
|
|
6623
6581
|
/*
|
6624
6582
|
* compute an Exponential Weighted moving average
|
@@ -7220,33 +7178,30 @@
|
|
7220
7178
|
return -1;
|
7221
7179
|
}
|
7222
7180
|
|
7223
|
-
var AbrController = /*#__PURE__*/function (
|
7224
|
-
_inheritsLoose(AbrController, _Logger);
|
7181
|
+
var AbrController = /*#__PURE__*/function () {
|
7225
7182
|
function AbrController(_hls) {
|
7226
|
-
var _this;
|
7227
|
-
|
7228
|
-
|
7229
|
-
|
7230
|
-
|
7231
|
-
|
7232
|
-
|
7233
|
-
|
7234
|
-
|
7235
|
-
|
7236
|
-
|
7237
|
-
|
7238
|
-
|
7239
|
-
|
7240
|
-
_this.bwEstimator = void 0;
|
7183
|
+
var _this = this;
|
7184
|
+
this.hls = void 0;
|
7185
|
+
this.lastLevelLoadSec = 0;
|
7186
|
+
this.lastLoadedFragLevel = -1;
|
7187
|
+
this.firstSelection = -1;
|
7188
|
+
this._nextAutoLevel = -1;
|
7189
|
+
this.nextAutoLevelKey = '';
|
7190
|
+
this.audioTracksByGroup = null;
|
7191
|
+
this.codecTiers = null;
|
7192
|
+
this.timer = -1;
|
7193
|
+
this.fragCurrent = null;
|
7194
|
+
this.partCurrent = null;
|
7195
|
+
this.bitrateTestDelay = 0;
|
7196
|
+
this.bwEstimator = void 0;
|
7241
7197
|
/*
|
7242
7198
|
This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
|
7243
7199
|
quickly enough to prevent underbuffering
|
7244
7200
|
*/
|
7245
|
-
|
7246
|
-
var
|
7247
|
-
|
7248
|
-
|
7249
|
-
hls = _assertThisInitialize.hls;
|
7201
|
+
this._abandonRulesCheck = function () {
|
7202
|
+
var frag = _this.fragCurrent,
|
7203
|
+
part = _this.partCurrent,
|
7204
|
+
hls = _this.hls;
|
7250
7205
|
var autoLevelEnabled = hls.autoLevelEnabled,
|
7251
7206
|
media = hls.media;
|
7252
7207
|
if (!frag || !media) {
|
@@ -7335,22 +7290,21 @@
|
|
7335
7290
|
_this.resetEstimator(nextLoadLevelBitrate);
|
7336
7291
|
}
|
7337
7292
|
_this.clearTimer();
|
7338
|
-
|
7293
|
+
logger.warn("[abr] Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + frag.level + " is loading too slowly;\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for down switch fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n TTFB estimate: " + (ttfb | 0) + " ms\n Current BW estimate: " + (isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown') + " bps\n New BW estimate: " + (_this.getBwEstimate() | 0) + " bps\n Switching to level " + nextLoadLevel + " @ " + (nextLoadLevelBitrate | 0) + " bps");
|
7339
7294
|
hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
|
7340
7295
|
frag: frag,
|
7341
7296
|
part: part,
|
7342
7297
|
stats: stats
|
7343
7298
|
});
|
7344
7299
|
};
|
7345
|
-
|
7346
|
-
|
7347
|
-
|
7348
|
-
return _this;
|
7300
|
+
this.hls = _hls;
|
7301
|
+
this.bwEstimator = this.initEstimator();
|
7302
|
+
this.registerListeners();
|
7349
7303
|
}
|
7350
7304
|
var _proto = AbrController.prototype;
|
7351
7305
|
_proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
|
7352
7306
|
if (abrEwmaDefaultEstimate) {
|
7353
|
-
|
7307
|
+
logger.log("setting initial bwe to " + abrEwmaDefaultEstimate);
|
7354
7308
|
this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
|
7355
7309
|
}
|
7356
7310
|
this.firstSelection = -1;
|
@@ -7595,13 +7549,13 @@
|
|
7595
7549
|
// cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
|
7596
7550
|
var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
|
7597
7551
|
maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
|
7598
|
-
|
7552
|
+
logger.info("[abr] bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
|
7599
7553
|
// don't use conservative factor on bitrate test
|
7600
7554
|
bwFactor = bwUpFactor = 1;
|
7601
7555
|
}
|
7602
7556
|
}
|
7603
7557
|
var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
|
7604
|
-
|
7558
|
+
logger.info("[abr] " + (bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
|
7605
7559
|
if (bestLevel > -1) {
|
7606
7560
|
return bestLevel;
|
7607
7561
|
}
|
@@ -7669,7 +7623,7 @@
|
|
7669
7623
|
currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
|
7670
7624
|
currentFrameRate = minFramerate;
|
7671
7625
|
currentBw = Math.max(currentBw, minBitrate);
|
7672
|
-
|
7626
|
+
logger.log("[abr] picked start tier " + JSON.stringify(startTier));
|
7673
7627
|
} else {
|
7674
7628
|
currentCodecSet = level == null ? void 0 : level.codecSet;
|
7675
7629
|
currentVideoRange = level == null ? void 0 : level.videoRange;
|
@@ -7696,11 +7650,11 @@
|
|
7696
7650
|
var levels = _this2.hls.levels;
|
7697
7651
|
var index = levels.indexOf(levelInfo);
|
7698
7652
|
if (decodingInfo.error) {
|
7699
|
-
|
7653
|
+
logger.warn("[abr] MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
|
7700
7654
|
} else if (!decodingInfo.supported) {
|
7701
|
-
|
7655
|
+
logger.warn("[abr] Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
|
7702
7656
|
if (index > -1 && levels.length > 1) {
|
7703
|
-
|
7657
|
+
logger.log("[abr] Removing unsupported level " + index);
|
7704
7658
|
_this2.hls.removeLevel(index);
|
7705
7659
|
}
|
7706
7660
|
}
|
@@ -7747,9 +7701,9 @@
|
|
7747
7701
|
var forcedAutoLevel = _this2.forcedAutoLevel;
|
7748
7702
|
if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
|
7749
7703
|
if (levelsSkipped.length) {
|
7750
|
-
|
7704
|
+
logger.trace("[abr] Skipped level(s) " + levelsSkipped.join(',') + " of " + maxAutoLevel + " max with CODECS and VIDEO-RANGE:\"" + levels[levelsSkipped[0]].codecs + "\" " + levels[levelsSkipped[0]].videoRange + "; not compatible with \"" + level.codecs + "\" " + currentVideoRange);
|
7751
7705
|
}
|
7752
|
-
|
7706
|
+
logger.info("[abr] switch candidate:" + selectionBaseLevel + "->" + i + " adjustedbw(" + Math.round(adjustedbw) + ")-bitrate=" + Math.round(adjustedbw - bitrate) + " ttfb:" + ttfbEstimateSec.toFixed(1) + " avgDuration:" + avgDuration.toFixed(1) + " maxFetchDuration:" + maxFetchDuration.toFixed(1) + " fetchDuration:" + fetchDuration.toFixed(1) + " firstSelection:" + firstSelection + " codecSet:" + currentCodecSet + " videoRange:" + currentVideoRange + " hls.loadLevel:" + loadLevel);
|
7753
7707
|
}
|
7754
7708
|
if (firstSelection) {
|
7755
7709
|
_this2.firstSelection = i;
|
@@ -7783,7 +7737,7 @@
|
|
7783
7737
|
}
|
7784
7738
|
var firstLevel = this.hls.firstLevel;
|
7785
7739
|
var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
|
7786
|
-
|
7740
|
+
logger.warn("[abr] Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
|
7787
7741
|
return clamped;
|
7788
7742
|
}
|
7789
7743
|
}, {
|
@@ -7836,7 +7790,7 @@
|
|
7836
7790
|
}
|
7837
7791
|
}]);
|
7838
7792
|
return AbrController;
|
7839
|
-
}(
|
7793
|
+
}();
|
7840
7794
|
|
7841
7795
|
/**
|
7842
7796
|
* @ignore
|
@@ -7867,17 +7821,13 @@
|
|
7867
7821
|
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
|
7868
7822
|
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
|
7869
7823
|
*/
|
7870
|
-
var TaskLoop = /*#__PURE__*/function (
|
7871
|
-
|
7872
|
-
|
7873
|
-
|
7874
|
-
|
7875
|
-
|
7876
|
-
|
7877
|
-
_this._tickInterval = null;
|
7878
|
-
_this._tickCallCount = 0;
|
7879
|
-
_this._boundTick = _this.tick.bind(_assertThisInitialized(_this));
|
7880
|
-
return _this;
|
7824
|
+
var TaskLoop = /*#__PURE__*/function () {
|
7825
|
+
function TaskLoop() {
|
7826
|
+
this._boundTick = void 0;
|
7827
|
+
this._tickTimer = null;
|
7828
|
+
this._tickInterval = null;
|
7829
|
+
this._tickCallCount = 0;
|
7830
|
+
this._boundTick = this.tick.bind(this);
|
7881
7831
|
}
|
7882
7832
|
var _proto = TaskLoop.prototype;
|
7883
7833
|
_proto.destroy = function destroy() {
|
@@ -7963,7 +7913,7 @@
|
|
7963
7913
|
*/;
|
7964
7914
|
_proto.doTick = function doTick() {};
|
7965
7915
|
return TaskLoop;
|
7966
|
-
}(
|
7916
|
+
}();
|
7967
7917
|
|
7968
7918
|
var FragmentState = {
|
7969
7919
|
NOT_LOADED: "NOT_LOADED",
|
@@ -8982,8 +8932,8 @@
|
|
8982
8932
|
var _frag$decryptdata;
|
8983
8933
|
var byteRangeStart = start;
|
8984
8934
|
var byteRangeEnd = end;
|
8985
|
-
if (frag.sn === 'initSegment' &&
|
8986
|
-
// MAP segment encrypted with method 'AES-128'
|
8935
|
+
if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
|
8936
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
8987
8937
|
// has the unencrypted size specified in the range.
|
8988
8938
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
8989
8939
|
var fragmentLen = end - start;
|
@@ -9016,9 +8966,6 @@
|
|
9016
8966
|
(part ? part : frag).stats.aborted = true;
|
9017
8967
|
return new LoadError(errorData);
|
9018
8968
|
}
|
9019
|
-
function isMethodFullSegmentAesCbc(method) {
|
9020
|
-
return method === 'AES-128' || method === 'AES-256';
|
9021
|
-
}
|
9022
8969
|
var LoadError = /*#__PURE__*/function (_Error) {
|
9023
8970
|
_inheritsLoose(LoadError, _Error);
|
9024
8971
|
function LoadError(data) {
|
@@ -9032,65 +8979,37 @@
|
|
9032
8979
|
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
9033
8980
|
|
9034
8981
|
var AESCrypto = /*#__PURE__*/function () {
|
9035
|
-
function AESCrypto(subtle, iv
|
8982
|
+
function AESCrypto(subtle, iv) {
|
9036
8983
|
this.subtle = void 0;
|
9037
8984
|
this.aesIV = void 0;
|
9038
|
-
this.aesMode = void 0;
|
9039
8985
|
this.subtle = subtle;
|
9040
8986
|
this.aesIV = iv;
|
9041
|
-
this.aesMode = aesMode;
|
9042
8987
|
}
|
9043
8988
|
var _proto = AESCrypto.prototype;
|
9044
8989
|
_proto.decrypt = function decrypt(data, key) {
|
9045
|
-
|
9046
|
-
|
9047
|
-
|
9048
|
-
|
9049
|
-
iv: this.aesIV
|
9050
|
-
}, key, data);
|
9051
|
-
case DecrypterAesMode.ctr:
|
9052
|
-
return this.subtle.decrypt({
|
9053
|
-
name: 'AES-CTR',
|
9054
|
-
counter: this.aesIV,
|
9055
|
-
length: 64
|
9056
|
-
},
|
9057
|
-
//64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
|
9058
|
-
key, data);
|
9059
|
-
default:
|
9060
|
-
throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
|
9061
|
-
}
|
8990
|
+
return this.subtle.decrypt({
|
8991
|
+
name: 'AES-CBC',
|
8992
|
+
iv: this.aesIV
|
8993
|
+
}, key, data);
|
9062
8994
|
};
|
9063
8995
|
return AESCrypto;
|
9064
8996
|
}();
|
9065
8997
|
|
9066
8998
|
var FastAESKey = /*#__PURE__*/function () {
|
9067
|
-
function FastAESKey(subtle, key
|
8999
|
+
function FastAESKey(subtle, key) {
|
9068
9000
|
this.subtle = void 0;
|
9069
9001
|
this.key = void 0;
|
9070
|
-
this.aesMode = void 0;
|
9071
9002
|
this.subtle = subtle;
|
9072
9003
|
this.key = key;
|
9073
|
-
this.aesMode = aesMode;
|
9074
9004
|
}
|
9075
9005
|
var _proto = FastAESKey.prototype;
|
9076
9006
|
_proto.expandKey = function expandKey() {
|
9077
|
-
var subtleAlgoName = getSubtleAlgoName(this.aesMode);
|
9078
9007
|
return this.subtle.importKey('raw', this.key, {
|
9079
|
-
name:
|
9008
|
+
name: 'AES-CBC'
|
9080
9009
|
}, false, ['encrypt', 'decrypt']);
|
9081
9010
|
};
|
9082
9011
|
return FastAESKey;
|
9083
9012
|
}();
|
9084
|
-
function getSubtleAlgoName(aesMode) {
|
9085
|
-
switch (aesMode) {
|
9086
|
-
case DecrypterAesMode.cbc:
|
9087
|
-
return 'AES-CBC';
|
9088
|
-
case DecrypterAesMode.ctr:
|
9089
|
-
return 'AES-CTR';
|
9090
|
-
default:
|
9091
|
-
throw new Error("[FastAESKey] invalid aes mode " + aesMode);
|
9092
|
-
}
|
9093
|
-
}
|
9094
9013
|
|
9095
9014
|
// PKCS7
|
9096
9015
|
function removePadding(array) {
|
@@ -9343,8 +9262,7 @@
|
|
9343
9262
|
this.currentIV = null;
|
9344
9263
|
this.currentResult = null;
|
9345
9264
|
this.useSoftware = void 0;
|
9346
|
-
this.
|
9347
|
-
this.enableSoftwareAES = config.enableSoftwareAES;
|
9265
|
+
this.useSoftware = config.enableSoftwareAES;
|
9348
9266
|
this.removePKCS7Padding = removePKCS7Padding;
|
9349
9267
|
// built in decryptor expects PKCS7 padding
|
9350
9268
|
if (removePKCS7Padding) {
|
@@ -9357,7 +9275,9 @@
|
|
9357
9275
|
/* no-op */
|
9358
9276
|
}
|
9359
9277
|
}
|
9360
|
-
|
9278
|
+
if (this.subtle === null) {
|
9279
|
+
this.useSoftware = true;
|
9280
|
+
}
|
9361
9281
|
}
|
9362
9282
|
var _proto = Decrypter.prototype;
|
9363
9283
|
_proto.destroy = function destroy() {
|
@@ -9394,11 +9314,11 @@
|
|
9394
9314
|
this.softwareDecrypter = null;
|
9395
9315
|
}
|
9396
9316
|
};
|
9397
|
-
_proto.decrypt = function decrypt(data, key, iv
|
9317
|
+
_proto.decrypt = function decrypt(data, key, iv) {
|
9398
9318
|
var _this = this;
|
9399
9319
|
if (this.useSoftware) {
|
9400
9320
|
return new Promise(function (resolve, reject) {
|
9401
|
-
_this.softwareDecrypt(new Uint8Array(data), key, iv
|
9321
|
+
_this.softwareDecrypt(new Uint8Array(data), key, iv);
|
9402
9322
|
var decryptResult = _this.flush();
|
9403
9323
|
if (decryptResult) {
|
9404
9324
|
resolve(decryptResult.buffer);
|
@@ -9407,20 +9327,16 @@
|
|
9407
9327
|
}
|
9408
9328
|
});
|
9409
9329
|
}
|
9410
|
-
return this.webCryptoDecrypt(new Uint8Array(data), key, iv
|
9330
|
+
return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
|
9411
9331
|
}
|
9412
9332
|
|
9413
9333
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
9414
9334
|
// data is handled in the flush() call
|
9415
9335
|
;
|
9416
|
-
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv
|
9336
|
+
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
|
9417
9337
|
var currentIV = this.currentIV,
|
9418
9338
|
currentResult = this.currentResult,
|
9419
9339
|
remainderData = this.remainderData;
|
9420
|
-
if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
|
9421
|
-
logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
|
9422
|
-
return null;
|
9423
|
-
}
|
9424
9340
|
this.logOnce('JS AES decrypt');
|
9425
9341
|
// The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
|
9426
9342
|
// This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
|
@@ -9453,12 +9369,12 @@
|
|
9453
9369
|
}
|
9454
9370
|
return result;
|
9455
9371
|
};
|
9456
|
-
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv
|
9372
|
+
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
|
9457
9373
|
var _this2 = this;
|
9458
9374
|
var subtle = this.subtle;
|
9459
9375
|
if (this.key !== key || !this.fastAesKey) {
|
9460
9376
|
this.key = key;
|
9461
|
-
this.fastAesKey = new FastAESKey(subtle, key
|
9377
|
+
this.fastAesKey = new FastAESKey(subtle, key);
|
9462
9378
|
}
|
9463
9379
|
return this.fastAesKey.expandKey().then(function (aesKey) {
|
9464
9380
|
// decrypt using web crypto
|
@@ -9466,25 +9382,22 @@
|
|
9466
9382
|
return Promise.reject(new Error('web crypto not initialized'));
|
9467
9383
|
}
|
9468
9384
|
_this2.logOnce('WebCrypto AES decrypt');
|
9469
|
-
var crypto = new AESCrypto(subtle, new Uint8Array(iv)
|
9385
|
+
var crypto = new AESCrypto(subtle, new Uint8Array(iv));
|
9470
9386
|
return crypto.decrypt(data.buffer, aesKey);
|
9471
9387
|
}).catch(function (err) {
|
9472
9388
|
logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
|
9473
|
-
return _this2.onWebCryptoError(data, key, iv
|
9389
|
+
return _this2.onWebCryptoError(data, key, iv);
|
9474
9390
|
});
|
9475
9391
|
};
|
9476
|
-
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv
|
9477
|
-
|
9478
|
-
|
9479
|
-
|
9480
|
-
|
9481
|
-
|
9482
|
-
|
9483
|
-
if (decryptResult) {
|
9484
|
-
return decryptResult.buffer;
|
9485
|
-
}
|
9392
|
+
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
|
9393
|
+
this.useSoftware = true;
|
9394
|
+
this.logEnabled = true;
|
9395
|
+
this.softwareDecrypt(data, key, iv);
|
9396
|
+
var decryptResult = this.flush();
|
9397
|
+
if (decryptResult) {
|
9398
|
+
return decryptResult.buffer;
|
9486
9399
|
}
|
9487
|
-
throw new Error('WebCrypto
|
9400
|
+
throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
|
9488
9401
|
};
|
9489
9402
|
_proto.getValidChunk = function getValidChunk(data) {
|
9490
9403
|
var currentChunk = data;
|
@@ -9538,7 +9451,7 @@
|
|
9538
9451
|
_inheritsLoose(BaseStreamController, _TaskLoop);
|
9539
9452
|
function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
|
9540
9453
|
var _this;
|
9541
|
-
_this = _TaskLoop.call(this
|
9454
|
+
_this = _TaskLoop.call(this) || this;
|
9542
9455
|
_this.hls = void 0;
|
9543
9456
|
_this.fragPrevious = null;
|
9544
9457
|
_this.fragCurrent = null;
|
@@ -9563,96 +9476,25 @@
|
|
9563
9476
|
_this.startFragRequested = false;
|
9564
9477
|
_this.decrypter = void 0;
|
9565
9478
|
_this.initPTS = [];
|
9566
|
-
_this.
|
9567
|
-
_this.
|
9568
|
-
_this.
|
9569
|
-
|
9570
|
-
|
9571
|
-
fragCurrent = _assertThisInitialize.fragCurrent,
|
9572
|
-
media = _assertThisInitialize.media,
|
9573
|
-
mediaBuffer = _assertThisInitialize.mediaBuffer,
|
9574
|
-
state = _assertThisInitialize.state;
|
9575
|
-
var currentTime = media ? media.currentTime : 0;
|
9576
|
-
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9577
|
-
_this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9578
|
-
if (_this.state === State.ENDED) {
|
9579
|
-
_this.resetLoadingState();
|
9580
|
-
} else if (fragCurrent) {
|
9581
|
-
// Seeking while frag load is in progress
|
9582
|
-
var tolerance = config.maxFragLookUpTolerance;
|
9583
|
-
var fragStartOffset = fragCurrent.start - tolerance;
|
9584
|
-
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9585
|
-
// if seeking out of buffered range or into new one
|
9586
|
-
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9587
|
-
var pastFragment = currentTime > fragEndOffset;
|
9588
|
-
// if the seek position is outside the current fragment range
|
9589
|
-
if (currentTime < fragStartOffset || pastFragment) {
|
9590
|
-
if (pastFragment && fragCurrent.loader) {
|
9591
|
-
_this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9592
|
-
fragCurrent.abortRequests();
|
9593
|
-
_this.resetLoadingState();
|
9594
|
-
}
|
9595
|
-
_this.fragPrevious = null;
|
9596
|
-
}
|
9597
|
-
}
|
9598
|
-
}
|
9599
|
-
if (media) {
|
9600
|
-
// Remove gap fragments
|
9601
|
-
_this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
|
9602
|
-
_this.lastCurrentTime = currentTime;
|
9603
|
-
if (!_this.loadingParts) {
|
9604
|
-
var bufferEnd = Math.max(bufferInfo.end, currentTime);
|
9605
|
-
var shouldLoadParts = _this.shouldLoadParts(_this.getLevelDetails(), bufferEnd);
|
9606
|
-
if (shouldLoadParts) {
|
9607
|
-
_this.log("LL-Part loading ON after seeking to " + currentTime.toFixed(2) + " with buffer @" + bufferEnd.toFixed(2));
|
9608
|
-
_this.loadingParts = shouldLoadParts;
|
9609
|
-
}
|
9610
|
-
}
|
9611
|
-
}
|
9612
|
-
|
9613
|
-
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9614
|
-
if (!_this.loadedmetadata && !bufferInfo.len) {
|
9615
|
-
_this.nextLoadPosition = _this.startPosition = currentTime;
|
9616
|
-
}
|
9617
|
-
|
9618
|
-
// Async tick to speed up processing
|
9619
|
-
_this.tickImmediate();
|
9620
|
-
};
|
9621
|
-
_this.onMediaEnded = function () {
|
9622
|
-
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9623
|
-
_this.startPosition = _this.lastCurrentTime = 0;
|
9624
|
-
if (_this.playlistType === PlaylistLevelType.MAIN) {
|
9625
|
-
_this.hls.trigger(Events.MEDIA_ENDED, {
|
9626
|
-
stalled: false
|
9627
|
-
});
|
9628
|
-
}
|
9629
|
-
};
|
9479
|
+
_this.onvseeking = null;
|
9480
|
+
_this.onvended = null;
|
9481
|
+
_this.logPrefix = '';
|
9482
|
+
_this.log = void 0;
|
9483
|
+
_this.warn = void 0;
|
9630
9484
|
_this.playlistType = playlistType;
|
9485
|
+
_this.logPrefix = logPrefix;
|
9486
|
+
_this.log = logger.log.bind(logger, logPrefix + ":");
|
9487
|
+
_this.warn = logger.warn.bind(logger, logPrefix + ":");
|
9631
9488
|
_this.hls = hls;
|
9632
9489
|
_this.fragmentLoader = new FragmentLoader(hls.config);
|
9633
9490
|
_this.keyLoader = keyLoader;
|
9634
9491
|
_this.fragmentTracker = fragmentTracker;
|
9635
9492
|
_this.config = hls.config;
|
9636
9493
|
_this.decrypter = new Decrypter(hls.config);
|
9494
|
+
hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
|
9637
9495
|
return _this;
|
9638
9496
|
}
|
9639
9497
|
var _proto = BaseStreamController.prototype;
|
9640
|
-
_proto.registerListeners = function registerListeners() {
|
9641
|
-
var hls = this.hls;
|
9642
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9643
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9644
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9645
|
-
hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9646
|
-
hls.on(Events.ERROR, this.onError, this);
|
9647
|
-
};
|
9648
|
-
_proto.unregisterListeners = function unregisterListeners() {
|
9649
|
-
var hls = this.hls;
|
9650
|
-
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9651
|
-
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9652
|
-
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9653
|
-
hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9654
|
-
hls.off(Events.ERROR, this.onError, this);
|
9655
|
-
};
|
9656
9498
|
_proto.doTick = function doTick() {
|
9657
9499
|
this.onTickEnd();
|
9658
9500
|
};
|
@@ -9676,12 +9518,6 @@
|
|
9676
9518
|
this.clearNextTick();
|
9677
9519
|
this.state = State.STOPPED;
|
9678
9520
|
};
|
9679
|
-
_proto.pauseBuffering = function pauseBuffering() {
|
9680
|
-
this.buffering = false;
|
9681
|
-
};
|
9682
|
-
_proto.resumeBuffering = function resumeBuffering() {
|
9683
|
-
this.buffering = true;
|
9684
|
-
};
|
9685
9521
|
_proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
|
9686
9522
|
// If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
|
9687
9523
|
// of nothing loading/loaded return false
|
@@ -9712,8 +9548,10 @@
|
|
9712
9548
|
};
|
9713
9549
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
9714
9550
|
var media = this.media = this.mediaBuffer = data.media;
|
9715
|
-
|
9716
|
-
|
9551
|
+
this.onvseeking = this.onMediaSeeking.bind(this);
|
9552
|
+
this.onvended = this.onMediaEnded.bind(this);
|
9553
|
+
media.addEventListener('seeking', this.onvseeking);
|
9554
|
+
media.addEventListener('ended', this.onvended);
|
9717
9555
|
var config = this.config;
|
9718
9556
|
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
|
9719
9557
|
this.startLoad(config.startPosition);
|
@@ -9727,9 +9565,10 @@
|
|
9727
9565
|
}
|
9728
9566
|
|
9729
9567
|
// remove video listeners
|
9730
|
-
if (media) {
|
9731
|
-
media.removeEventListener('seeking', this.
|
9732
|
-
media.removeEventListener('ended', this.
|
9568
|
+
if (media && this.onvseeking && this.onvended) {
|
9569
|
+
media.removeEventListener('seeking', this.onvseeking);
|
9570
|
+
media.removeEventListener('ended', this.onvended);
|
9571
|
+
this.onvseeking = this.onvended = null;
|
9733
9572
|
}
|
9734
9573
|
if (this.keyLoader) {
|
9735
9574
|
this.keyLoader.detach();
|
@@ -9739,8 +9578,54 @@
|
|
9739
9578
|
this.fragmentTracker.removeAllFragments();
|
9740
9579
|
this.stopLoad();
|
9741
9580
|
};
|
9742
|
-
_proto.
|
9743
|
-
|
9581
|
+
_proto.onMediaSeeking = function onMediaSeeking() {
|
9582
|
+
var config = this.config,
|
9583
|
+
fragCurrent = this.fragCurrent,
|
9584
|
+
media = this.media,
|
9585
|
+
mediaBuffer = this.mediaBuffer,
|
9586
|
+
state = this.state;
|
9587
|
+
var currentTime = media ? media.currentTime : 0;
|
9588
|
+
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9589
|
+
this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9590
|
+
if (this.state === State.ENDED) {
|
9591
|
+
this.resetLoadingState();
|
9592
|
+
} else if (fragCurrent) {
|
9593
|
+
// Seeking while frag load is in progress
|
9594
|
+
var tolerance = config.maxFragLookUpTolerance;
|
9595
|
+
var fragStartOffset = fragCurrent.start - tolerance;
|
9596
|
+
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9597
|
+
// if seeking out of buffered range or into new one
|
9598
|
+
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9599
|
+
var pastFragment = currentTime > fragEndOffset;
|
9600
|
+
// if the seek position is outside the current fragment range
|
9601
|
+
if (currentTime < fragStartOffset || pastFragment) {
|
9602
|
+
if (pastFragment && fragCurrent.loader) {
|
9603
|
+
this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9604
|
+
fragCurrent.abortRequests();
|
9605
|
+
this.resetLoadingState();
|
9606
|
+
}
|
9607
|
+
this.fragPrevious = null;
|
9608
|
+
}
|
9609
|
+
}
|
9610
|
+
}
|
9611
|
+
if (media) {
|
9612
|
+
// Remove gap fragments
|
9613
|
+
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
9614
|
+
this.lastCurrentTime = currentTime;
|
9615
|
+
}
|
9616
|
+
|
9617
|
+
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9618
|
+
if (!this.loadedmetadata && !bufferInfo.len) {
|
9619
|
+
this.nextLoadPosition = this.startPosition = currentTime;
|
9620
|
+
}
|
9621
|
+
|
9622
|
+
// Async tick to speed up processing
|
9623
|
+
this.tickImmediate();
|
9624
|
+
};
|
9625
|
+
_proto.onMediaEnded = function onMediaEnded() {
|
9626
|
+
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9627
|
+
this.startPosition = this.lastCurrentTime = 0;
|
9628
|
+
};
|
9744
9629
|
_proto.onManifestLoaded = function onManifestLoaded(event, data) {
|
9745
9630
|
this.startTimeOffset = data.startTimeOffset;
|
9746
9631
|
this.initPTS = [];
|
@@ -9750,7 +9635,7 @@
|
|
9750
9635
|
this.stopLoad();
|
9751
9636
|
_TaskLoop.prototype.onHandlerDestroying.call(this);
|
9752
9637
|
// @ts-ignore
|
9753
|
-
this.hls =
|
9638
|
+
this.hls = null;
|
9754
9639
|
};
|
9755
9640
|
_proto.onHandlerDestroyed = function onHandlerDestroyed() {
|
9756
9641
|
this.state = State.STOPPED;
|
@@ -9880,10 +9765,10 @@
|
|
9880
9765
|
var decryptData = frag.decryptdata;
|
9881
9766
|
|
9882
9767
|
// check to see if the payload needs to be decrypted
|
9883
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
9768
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
9884
9769
|
var startTime = self.performance.now();
|
9885
9770
|
// decrypt init segment data
|
9886
|
-
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
9771
|
+
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
9887
9772
|
hls.trigger(Events.ERROR, {
|
9888
9773
|
type: ErrorTypes.MEDIA_ERROR,
|
9889
9774
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -9996,7 +9881,7 @@
|
|
9996
9881
|
}
|
9997
9882
|
var keyLoadingPromise = null;
|
9998
9883
|
if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
|
9999
|
-
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.
|
9884
|
+
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level);
|
10000
9885
|
this.state = State.KEY_LOADING;
|
10001
9886
|
this.fragCurrent = frag;
|
10002
9887
|
keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
|
@@ -10017,16 +9902,8 @@
|
|
10017
9902
|
} else if (!frag.encrypted && details.encryptedFragments.length) {
|
10018
9903
|
this.keyLoader.loadClear(frag, details.encryptedFragments);
|
10019
9904
|
}
|
10020
|
-
var fragPrevious = this.fragPrevious;
|
10021
|
-
if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
|
10022
|
-
var shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
|
10023
|
-
if (shouldLoadParts !== this.loadingParts) {
|
10024
|
-
this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " loading sn " + (fragPrevious == null ? void 0 : fragPrevious.sn) + "->" + frag.sn);
|
10025
|
-
this.loadingParts = shouldLoadParts;
|
10026
|
-
}
|
10027
|
-
}
|
10028
9905
|
targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
|
10029
|
-
if (this.
|
9906
|
+
if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {
|
10030
9907
|
var partList = details.partList;
|
10031
9908
|
if (partList && progressCallback) {
|
10032
9909
|
if (targetBufferTime > frag.end && details.fragmentHint) {
|
@@ -10035,7 +9912,7 @@
|
|
10035
9912
|
var partIndex = this.getNextPart(partList, frag, targetBufferTime);
|
10036
9913
|
if (partIndex > -1) {
|
10037
9914
|
var part = partList[partIndex];
|
10038
|
-
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.
|
9915
|
+
this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
|
10039
9916
|
this.nextLoadPosition = part.start + part.duration;
|
10040
9917
|
this.state = State.FRAG_LOADING;
|
10041
9918
|
var _result;
|
@@ -10068,14 +9945,7 @@
|
|
10068
9945
|
}
|
10069
9946
|
}
|
10070
9947
|
}
|
10071
|
-
|
10072
|
-
this.log("LL-Part loading OFF after next part miss @" + targetBufferTime.toFixed(2));
|
10073
|
-
this.loadingParts = false;
|
10074
|
-
} else if (!frag.url) {
|
10075
|
-
// Selected fragment hint for part but not loading parts
|
10076
|
-
return Promise.resolve(null);
|
10077
|
-
}
|
10078
|
-
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)));
|
9948
|
+
this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
|
10079
9949
|
// Don't update nextLoadPosition for fragments which are not buffered
|
10080
9950
|
if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
|
10081
9951
|
this.nextLoadPosition = frag.start + frag.duration;
|
@@ -10177,36 +10047,8 @@
|
|
10177
10047
|
if (part) {
|
10178
10048
|
part.stats.parsing.end = now;
|
10179
10049
|
}
|
10180
|
-
// See if part loading should be disabled/enabled based on buffer and playback position.
|
10181
|
-
if (frag.sn !== 'initSegment') {
|
10182
|
-
var levelDetails = this.getLevelDetails();
|
10183
|
-
var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
|
10184
|
-
var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
|
10185
|
-
if (shouldLoadParts !== this.loadingParts) {
|
10186
|
-
this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
|
10187
|
-
this.loadingParts = shouldLoadParts;
|
10188
|
-
}
|
10189
|
-
}
|
10190
10050
|
this.updateLevelTiming(frag, part, level, chunkMeta.partial);
|
10191
10051
|
};
|
10192
|
-
_proto.shouldLoadParts = function shouldLoadParts(details, bufferEnd) {
|
10193
|
-
if (this.config.lowLatencyMode) {
|
10194
|
-
if (!details) {
|
10195
|
-
return this.loadingParts;
|
10196
|
-
}
|
10197
|
-
if (details != null && details.partList) {
|
10198
|
-
var _details$fragmentHint;
|
10199
|
-
// Buffer must be ahead of first part + duration of parts after last segment
|
10200
|
-
// and playback must be at or past segment adjacent to part list
|
10201
|
-
var firstPart = details.partList[0];
|
10202
|
-
var safePartStart = firstPart.end + (((_details$fragmentHint = details.fragmentHint) == null ? void 0 : _details$fragmentHint.duration) || 0);
|
10203
|
-
if (bufferEnd >= safePartStart && this.lastCurrentTime > firstPart.start - firstPart.fragment.duration) {
|
10204
|
-
return true;
|
10205
|
-
}
|
10206
|
-
}
|
10207
|
-
}
|
10208
|
-
return false;
|
10209
|
-
};
|
10210
10052
|
_proto.getCurrentContext = function getCurrentContext(chunkMeta) {
|
10211
10053
|
var levels = this.levels,
|
10212
10054
|
fragCurrent = this.fragCurrent;
|
@@ -10341,8 +10183,7 @@
|
|
10341
10183
|
// find fragment index, contiguous with end of buffer position
|
10342
10184
|
var config = this.config;
|
10343
10185
|
var start = fragments[0].start;
|
10344
|
-
var
|
10345
|
-
var frag = null;
|
10186
|
+
var frag;
|
10346
10187
|
if (levelDetails.live) {
|
10347
10188
|
var initialLiveManifestSize = config.initialLiveManifestSize;
|
10348
10189
|
if (fragLen < initialLiveManifestSize) {
|
@@ -10354,10 +10195,6 @@
|
|
10354
10195
|
// Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that
|
10355
10196
|
// we get the fragment matching that start time
|
10356
10197
|
if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1 || pos < start) {
|
10357
|
-
if (canLoadParts && !this.loadingParts) {
|
10358
|
-
this.log("LL-Part loading ON for initial live fragment");
|
10359
|
-
this.loadingParts = true;
|
10360
|
-
}
|
10361
10198
|
frag = this.getInitialLiveFragment(levelDetails, fragments);
|
10362
10199
|
this.startPosition = this.nextLoadPosition = frag ? this.hls.liveSyncPosition || frag.start : pos;
|
10363
10200
|
}
|
@@ -10368,7 +10205,7 @@
|
|
10368
10205
|
|
10369
10206
|
// If we haven't run into any special cases already, just load the fragment most closely matching the requested position
|
10370
10207
|
if (!frag) {
|
10371
|
-
var end =
|
10208
|
+
var end = config.lowLatencyMode ? levelDetails.partEnd : levelDetails.fragmentEnd;
|
10372
10209
|
frag = this.getFragmentAtPosition(pos, end, levelDetails);
|
10373
10210
|
}
|
10374
10211
|
return this.mapToInitFragWhenRequired(frag);
|
@@ -10482,7 +10319,7 @@
|
|
10482
10319
|
var fragmentHint = levelDetails.fragmentHint;
|
10483
10320
|
var tolerance = config.maxFragLookUpTolerance;
|
10484
10321
|
var partList = levelDetails.partList;
|
10485
|
-
var loadingParts = !!(
|
10322
|
+
var loadingParts = !!(config.lowLatencyMode && partList != null && partList.length && fragmentHint);
|
10486
10323
|
if (loadingParts && fragmentHint && !this.bitrateTest) {
|
10487
10324
|
// Include incomplete fragment with parts at end
|
10488
10325
|
fragments = fragments.concat(fragmentHint);
|
@@ -10669,7 +10506,7 @@
|
|
10669
10506
|
errorAction.resolved = true;
|
10670
10507
|
}
|
10671
10508
|
} else {
|
10672
|
-
|
10509
|
+
logger.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
|
10673
10510
|
return;
|
10674
10511
|
}
|
10675
10512
|
} else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
|
@@ -11069,7 +10906,6 @@
|
|
11069
10906
|
*/
|
11070
10907
|
function getAudioConfig(observer, data, offset, audioCodec) {
|
11071
10908
|
var adtsObjectType;
|
11072
|
-
var originalAdtsObjectType;
|
11073
10909
|
var adtsExtensionSamplingIndex;
|
11074
10910
|
var adtsChannelConfig;
|
11075
10911
|
var config;
|
@@ -11077,7 +10913,7 @@
|
|
11077
10913
|
var manifestCodec = audioCodec;
|
11078
10914
|
var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
|
11079
10915
|
// byte 2
|
11080
|
-
adtsObjectType =
|
10916
|
+
adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
11081
10917
|
var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
|
11082
10918
|
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
|
11083
10919
|
var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
|
@@ -11094,8 +10930,8 @@
|
|
11094
10930
|
// byte 3
|
11095
10931
|
adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
|
11096
10932
|
logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
|
11097
|
-
//
|
11098
|
-
if (/firefox
|
10933
|
+
// firefox: freq less than 24kHz = AAC SBR (HE-AAC)
|
10934
|
+
if (/firefox/i.test(userAgent)) {
|
11099
10935
|
if (adtsSamplingIndex >= 6) {
|
11100
10936
|
adtsObjectType = 5;
|
11101
10937
|
config = new Array(4);
|
@@ -11189,7 +11025,6 @@
|
|
11189
11025
|
samplerate: adtsSamplingRates[adtsSamplingIndex],
|
11190
11026
|
channelCount: adtsChannelConfig,
|
11191
11027
|
codec: 'mp4a.40.' + adtsObjectType,
|
11192
|
-
parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
|
11193
11028
|
manifestCodec: manifestCodec
|
11194
11029
|
};
|
11195
11030
|
}
|
@@ -11244,8 +11079,7 @@
|
|
11244
11079
|
track.channelCount = config.channelCount;
|
11245
11080
|
track.codec = config.codec;
|
11246
11081
|
track.manifestCodec = config.manifestCodec;
|
11247
|
-
track.
|
11248
|
-
logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11082
|
+
logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11249
11083
|
}
|
11250
11084
|
}
|
11251
11085
|
function getFrameDuration(samplerate) {
|
@@ -11843,110 +11677,6 @@
|
|
11843
11677
|
logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
|
11844
11678
|
}
|
11845
11679
|
};
|
11846
|
-
_proto.parseNALu = function parseNALu(track, array) {
|
11847
|
-
var len = array.byteLength;
|
11848
|
-
var state = track.naluState || 0;
|
11849
|
-
var lastState = state;
|
11850
|
-
var units = [];
|
11851
|
-
var i = 0;
|
11852
|
-
var value;
|
11853
|
-
var overflow;
|
11854
|
-
var unitType;
|
11855
|
-
var lastUnitStart = -1;
|
11856
|
-
var lastUnitType = 0;
|
11857
|
-
// logger.log('PES:' + Hex.hexDump(array));
|
11858
|
-
|
11859
|
-
if (state === -1) {
|
11860
|
-
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
11861
|
-
lastUnitStart = 0;
|
11862
|
-
// NALu type is value read from offset 0
|
11863
|
-
lastUnitType = this.getNALuType(array, 0);
|
11864
|
-
state = 0;
|
11865
|
-
i = 1;
|
11866
|
-
}
|
11867
|
-
while (i < len) {
|
11868
|
-
value = array[i++];
|
11869
|
-
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
11870
|
-
if (!state) {
|
11871
|
-
state = value ? 0 : 1;
|
11872
|
-
continue;
|
11873
|
-
}
|
11874
|
-
if (state === 1) {
|
11875
|
-
state = value ? 0 : 2;
|
11876
|
-
continue;
|
11877
|
-
}
|
11878
|
-
// here we have state either equal to 2 or 3
|
11879
|
-
if (!value) {
|
11880
|
-
state = 3;
|
11881
|
-
} else if (value === 1) {
|
11882
|
-
overflow = i - state - 1;
|
11883
|
-
if (lastUnitStart >= 0) {
|
11884
|
-
var unit = {
|
11885
|
-
data: array.subarray(lastUnitStart, overflow),
|
11886
|
-
type: lastUnitType
|
11887
|
-
};
|
11888
|
-
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
|
11889
|
-
units.push(unit);
|
11890
|
-
} else {
|
11891
|
-
// lastUnitStart is undefined => this is the first start code found in this PES packet
|
11892
|
-
// first check if start code delimiter is overlapping between 2 PES packets,
|
11893
|
-
// ie it started in last packet (lastState not zero)
|
11894
|
-
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
11895
|
-
var lastUnit = this.getLastNalUnit(track.samples);
|
11896
|
-
if (lastUnit) {
|
11897
|
-
if (lastState && i <= 4 - lastState) {
|
11898
|
-
// start delimiter overlapping between PES packets
|
11899
|
-
// strip start delimiter bytes from the end of last NAL unit
|
11900
|
-
// check if lastUnit had a state different from zero
|
11901
|
-
if (lastUnit.state) {
|
11902
|
-
// strip last bytes
|
11903
|
-
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
|
11904
|
-
}
|
11905
|
-
}
|
11906
|
-
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
|
11907
|
-
|
11908
|
-
if (overflow > 0) {
|
11909
|
-
// logger.log('first NALU found with overflow:' + overflow);
|
11910
|
-
lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
|
11911
|
-
lastUnit.state = 0;
|
11912
|
-
}
|
11913
|
-
}
|
11914
|
-
}
|
11915
|
-
// check if we can read unit type
|
11916
|
-
if (i < len) {
|
11917
|
-
unitType = this.getNALuType(array, i);
|
11918
|
-
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
11919
|
-
lastUnitStart = i;
|
11920
|
-
lastUnitType = unitType;
|
11921
|
-
state = 0;
|
11922
|
-
} else {
|
11923
|
-
// not enough byte to read unit type. let's read it on next PES parsing
|
11924
|
-
state = -1;
|
11925
|
-
}
|
11926
|
-
} else {
|
11927
|
-
state = 0;
|
11928
|
-
}
|
11929
|
-
}
|
11930
|
-
if (lastUnitStart >= 0 && state >= 0) {
|
11931
|
-
var _unit = {
|
11932
|
-
data: array.subarray(lastUnitStart, len),
|
11933
|
-
type: lastUnitType,
|
11934
|
-
state: state
|
11935
|
-
};
|
11936
|
-
units.push(_unit);
|
11937
|
-
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
11938
|
-
}
|
11939
|
-
// no NALu found
|
11940
|
-
if (units.length === 0) {
|
11941
|
-
// append pes.data to previous NAL unit
|
11942
|
-
var _lastUnit = this.getLastNalUnit(track.samples);
|
11943
|
-
if (_lastUnit) {
|
11944
|
-
_lastUnit.data = appendUint8Array(_lastUnit.data, array);
|
11945
|
-
}
|
11946
|
-
}
|
11947
|
-
track.naluState = state;
|
11948
|
-
return units;
|
11949
|
-
};
|
11950
11680
|
return BaseVideoParser;
|
11951
11681
|
}();
|
11952
11682
|
|
@@ -12101,236 +11831,78 @@
|
|
12101
11831
|
;
|
12102
11832
|
_proto.readUInt = function readUInt() {
|
12103
11833
|
return this.readBits(32);
|
12104
|
-
};
|
12105
|
-
return ExpGolomb;
|
12106
|
-
}();
|
12107
|
-
|
12108
|
-
var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
|
12109
|
-
_inheritsLoose(AvcVideoParser, _BaseVideoParser);
|
12110
|
-
function AvcVideoParser() {
|
12111
|
-
return _BaseVideoParser.apply(this, arguments) || this;
|
12112
11834
|
}
|
12113
|
-
var _proto = AvcVideoParser.prototype;
|
12114
|
-
_proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
|
12115
|
-
var _this = this;
|
12116
|
-
var units = this.parseNALu(track, pes.data);
|
12117
|
-
var VideoSample = this.VideoSample;
|
12118
|
-
var push;
|
12119
|
-
var spsfound = false;
|
12120
|
-
// free pes.data to save up some memory
|
12121
|
-
pes.data = null;
|
12122
11835
|
|
12123
|
-
|
12124
|
-
|
12125
|
-
|
12126
|
-
|
12127
|
-
|
11836
|
+
/**
|
11837
|
+
* Advance the ExpGolomb decoder past a scaling list. The scaling
|
11838
|
+
* list is optionally transmitted as part of a sequence parameter
|
11839
|
+
* set and is not relevant to transmuxing.
|
11840
|
+
* @param count the number of entries in this scaling list
|
11841
|
+
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
11842
|
+
*/;
|
11843
|
+
_proto.skipScalingList = function skipScalingList(count) {
|
11844
|
+
var lastScale = 8;
|
11845
|
+
var nextScale = 8;
|
11846
|
+
var deltaScale;
|
11847
|
+
for (var j = 0; j < count; j++) {
|
11848
|
+
if (nextScale !== 0) {
|
11849
|
+
deltaScale = this.readEG();
|
11850
|
+
nextScale = (lastScale + deltaScale + 256) % 256;
|
11851
|
+
}
|
11852
|
+
lastScale = nextScale === 0 ? lastScale : nextScale;
|
12128
11853
|
}
|
12129
|
-
|
12130
|
-
|
12131
|
-
|
12132
|
-
|
12133
|
-
|
12134
|
-
|
12135
|
-
|
12136
|
-
|
12137
|
-
|
12138
|
-
|
12139
|
-
|
12140
|
-
|
12141
|
-
|
12142
|
-
|
12143
|
-
|
12144
|
-
|
12145
|
-
|
12146
|
-
|
12147
|
-
|
12148
|
-
|
12149
|
-
|
12150
|
-
|
12151
|
-
|
12152
|
-
|
12153
|
-
|
12154
|
-
|
12155
|
-
|
12156
|
-
|
12157
|
-
|
12158
|
-
|
12159
|
-
|
12160
|
-
|
12161
|
-
|
12162
|
-
|
12163
|
-
|
12164
|
-
|
12165
|
-
|
12166
|
-
|
12167
|
-
|
12168
|
-
|
12169
|
-
|
12170
|
-
|
12171
|
-
|
12172
|
-
|
12173
|
-
|
12174
|
-
|
12175
|
-
if (
|
12176
|
-
|
12177
|
-
|
12178
|
-
|
12179
|
-
|
12180
|
-
|
12181
|
-
// SEI
|
12182
|
-
case 6:
|
12183
|
-
{
|
12184
|
-
push = true;
|
12185
|
-
parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
|
12186
|
-
break;
|
12187
|
-
// SPS
|
12188
|
-
}
|
12189
|
-
case 7:
|
12190
|
-
{
|
12191
|
-
var _track$pixelRatio, _track$pixelRatio2;
|
12192
|
-
push = true;
|
12193
|
-
spsfound = true;
|
12194
|
-
var sps = unit.data;
|
12195
|
-
var config = _this.readSPS(sps);
|
12196
|
-
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]) {
|
12197
|
-
track.width = config.width;
|
12198
|
-
track.height = config.height;
|
12199
|
-
track.pixelRatio = config.pixelRatio;
|
12200
|
-
track.sps = [sps];
|
12201
|
-
track.duration = duration;
|
12202
|
-
var codecarray = sps.subarray(1, 4);
|
12203
|
-
var codecstring = 'avc1.';
|
12204
|
-
for (var i = 0; i < 3; i++) {
|
12205
|
-
var h = codecarray[i].toString(16);
|
12206
|
-
if (h.length < 2) {
|
12207
|
-
h = '0' + h;
|
12208
|
-
}
|
12209
|
-
codecstring += h;
|
12210
|
-
}
|
12211
|
-
track.codec = codecstring;
|
12212
|
-
}
|
12213
|
-
break;
|
12214
|
-
}
|
12215
|
-
// PPS
|
12216
|
-
case 8:
|
12217
|
-
push = true;
|
12218
|
-
track.pps = [unit.data];
|
12219
|
-
break;
|
12220
|
-
// AUD
|
12221
|
-
case 9:
|
12222
|
-
push = true;
|
12223
|
-
track.audFound = true;
|
12224
|
-
if (VideoSample) {
|
12225
|
-
_this.pushAccessUnit(VideoSample, track);
|
12226
|
-
}
|
12227
|
-
VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
|
12228
|
-
break;
|
12229
|
-
// Filler Data
|
12230
|
-
case 12:
|
12231
|
-
push = true;
|
12232
|
-
break;
|
12233
|
-
default:
|
12234
|
-
push = false;
|
12235
|
-
if (VideoSample) {
|
12236
|
-
VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
|
12237
|
-
}
|
12238
|
-
break;
|
12239
|
-
}
|
12240
|
-
if (VideoSample && push) {
|
12241
|
-
var _units = VideoSample.units;
|
12242
|
-
_units.push(unit);
|
12243
|
-
}
|
12244
|
-
});
|
12245
|
-
// if last PES packet, push samples
|
12246
|
-
if (last && VideoSample) {
|
12247
|
-
this.pushAccessUnit(VideoSample, track);
|
12248
|
-
this.VideoSample = null;
|
12249
|
-
}
|
12250
|
-
};
|
12251
|
-
_proto.getNALuType = function getNALuType(data, offset) {
|
12252
|
-
return data[offset] & 0x1f;
|
12253
|
-
};
|
12254
|
-
_proto.readSliceType = function readSliceType(data) {
|
12255
|
-
var eg = new ExpGolomb(data);
|
12256
|
-
// skip NALu type
|
12257
|
-
eg.readUByte();
|
12258
|
-
// discard first_mb_in_slice
|
12259
|
-
eg.readUEG();
|
12260
|
-
// return slice_type
|
12261
|
-
return eg.readUEG();
|
12262
|
-
}
|
12263
|
-
|
12264
|
-
/**
|
12265
|
-
* The scaling list is optionally transmitted as part of a sequence parameter
|
12266
|
-
* set and is not relevant to transmuxing.
|
12267
|
-
* @param count the number of entries in this scaling list
|
12268
|
-
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
12269
|
-
*/;
|
12270
|
-
_proto.skipScalingList = function skipScalingList(count, reader) {
|
12271
|
-
var lastScale = 8;
|
12272
|
-
var nextScale = 8;
|
12273
|
-
var deltaScale;
|
12274
|
-
for (var j = 0; j < count; j++) {
|
12275
|
-
if (nextScale !== 0) {
|
12276
|
-
deltaScale = reader.readEG();
|
12277
|
-
nextScale = (lastScale + deltaScale + 256) % 256;
|
12278
|
-
}
|
12279
|
-
lastScale = nextScale === 0 ? lastScale : nextScale;
|
12280
|
-
}
|
12281
|
-
}
|
12282
|
-
|
12283
|
-
/**
|
12284
|
-
* Read a sequence parameter set and return some interesting video
|
12285
|
-
* properties. A sequence parameter set is the H264 metadata that
|
12286
|
-
* describes the properties of upcoming video frames.
|
12287
|
-
* @returns an object with configuration parsed from the
|
12288
|
-
* sequence parameter set, including the dimensions of the
|
12289
|
-
* associated video frames.
|
12290
|
-
*/;
|
12291
|
-
_proto.readSPS = function readSPS(sps) {
|
12292
|
-
var eg = new ExpGolomb(sps);
|
12293
|
-
var frameCropLeftOffset = 0;
|
12294
|
-
var frameCropRightOffset = 0;
|
12295
|
-
var frameCropTopOffset = 0;
|
12296
|
-
var frameCropBottomOffset = 0;
|
12297
|
-
var numRefFramesInPicOrderCntCycle;
|
12298
|
-
var scalingListCount;
|
12299
|
-
var i;
|
12300
|
-
var readUByte = eg.readUByte.bind(eg);
|
12301
|
-
var readBits = eg.readBits.bind(eg);
|
12302
|
-
var readUEG = eg.readUEG.bind(eg);
|
12303
|
-
var readBoolean = eg.readBoolean.bind(eg);
|
12304
|
-
var skipBits = eg.skipBits.bind(eg);
|
12305
|
-
var skipEG = eg.skipEG.bind(eg);
|
12306
|
-
var skipUEG = eg.skipUEG.bind(eg);
|
12307
|
-
var skipScalingList = this.skipScalingList.bind(this);
|
12308
|
-
readUByte();
|
12309
|
-
var profileIdc = readUByte(); // profile_idc
|
12310
|
-
readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
|
12311
|
-
skipBits(3); // reserved_zero_3bits u(3),
|
12312
|
-
readUByte(); // level_idc u(8)
|
12313
|
-
skipUEG(); // seq_parameter_set_id
|
12314
|
-
// some profiles have more optional data we don't need
|
12315
|
-
if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
|
12316
|
-
var chromaFormatIdc = readUEG();
|
12317
|
-
if (chromaFormatIdc === 3) {
|
12318
|
-
skipBits(1);
|
12319
|
-
} // separate_colour_plane_flag
|
12320
|
-
|
12321
|
-
skipUEG(); // bit_depth_luma_minus8
|
12322
|
-
skipUEG(); // bit_depth_chroma_minus8
|
12323
|
-
skipBits(1); // qpprime_y_zero_transform_bypass_flag
|
12324
|
-
if (readBoolean()) {
|
12325
|
-
// seq_scaling_matrix_present_flag
|
12326
|
-
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
|
12327
|
-
for (i = 0; i < scalingListCount; i++) {
|
12328
|
-
if (readBoolean()) {
|
12329
|
-
// seq_scaling_list_present_flag[ i ]
|
12330
|
-
if (i < 6) {
|
12331
|
-
skipScalingList(16, eg);
|
12332
|
-
} else {
|
12333
|
-
skipScalingList(64, eg);
|
11854
|
+
}
|
11855
|
+
|
11856
|
+
/**
|
11857
|
+
* Read a sequence parameter set and return some interesting video
|
11858
|
+
* properties. A sequence parameter set is the H264 metadata that
|
11859
|
+
* describes the properties of upcoming video frames.
|
11860
|
+
* @returns an object with configuration parsed from the
|
11861
|
+
* sequence parameter set, including the dimensions of the
|
11862
|
+
* associated video frames.
|
11863
|
+
*/;
|
11864
|
+
_proto.readSPS = function readSPS() {
|
11865
|
+
var frameCropLeftOffset = 0;
|
11866
|
+
var frameCropRightOffset = 0;
|
11867
|
+
var frameCropTopOffset = 0;
|
11868
|
+
var frameCropBottomOffset = 0;
|
11869
|
+
var numRefFramesInPicOrderCntCycle;
|
11870
|
+
var scalingListCount;
|
11871
|
+
var i;
|
11872
|
+
var readUByte = this.readUByte.bind(this);
|
11873
|
+
var readBits = this.readBits.bind(this);
|
11874
|
+
var readUEG = this.readUEG.bind(this);
|
11875
|
+
var readBoolean = this.readBoolean.bind(this);
|
11876
|
+
var skipBits = this.skipBits.bind(this);
|
11877
|
+
var skipEG = this.skipEG.bind(this);
|
11878
|
+
var skipUEG = this.skipUEG.bind(this);
|
11879
|
+
var skipScalingList = this.skipScalingList.bind(this);
|
11880
|
+
readUByte();
|
11881
|
+
var profileIdc = readUByte(); // profile_idc
|
11882
|
+
readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
|
11883
|
+
skipBits(3); // reserved_zero_3bits u(3),
|
11884
|
+
readUByte(); // level_idc u(8)
|
11885
|
+
skipUEG(); // seq_parameter_set_id
|
11886
|
+
// some profiles have more optional data we don't need
|
11887
|
+
if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
|
11888
|
+
var chromaFormatIdc = readUEG();
|
11889
|
+
if (chromaFormatIdc === 3) {
|
11890
|
+
skipBits(1);
|
11891
|
+
} // separate_colour_plane_flag
|
11892
|
+
|
11893
|
+
skipUEG(); // bit_depth_luma_minus8
|
11894
|
+
skipUEG(); // bit_depth_chroma_minus8
|
11895
|
+
skipBits(1); // qpprime_y_zero_transform_bypass_flag
|
11896
|
+
if (readBoolean()) {
|
11897
|
+
// seq_scaling_matrix_present_flag
|
11898
|
+
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
|
11899
|
+
for (i = 0; i < scalingListCount; i++) {
|
11900
|
+
if (readBoolean()) {
|
11901
|
+
// seq_scaling_list_present_flag[ i ]
|
11902
|
+
if (i < 6) {
|
11903
|
+
skipScalingList(16);
|
11904
|
+
} else {
|
11905
|
+
skipScalingList(64);
|
12334
11906
|
}
|
12335
11907
|
}
|
12336
11908
|
}
|
@@ -12435,24 +12007,26 @@
|
|
12435
12007
|
pixelRatio: pixelRatio
|
12436
12008
|
};
|
12437
12009
|
};
|
12438
|
-
|
12439
|
-
|
12010
|
+
_proto.readSliceType = function readSliceType() {
|
12011
|
+
// skip NALu type
|
12012
|
+
this.readUByte();
|
12013
|
+
// discard first_mb_in_slice
|
12014
|
+
this.readUEG();
|
12015
|
+
// return slice_type
|
12016
|
+
return this.readUEG();
|
12017
|
+
};
|
12018
|
+
return ExpGolomb;
|
12019
|
+
}();
|
12440
12020
|
|
12441
|
-
var
|
12442
|
-
_inheritsLoose(
|
12443
|
-
function
|
12444
|
-
|
12445
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
12446
|
-
args[_key] = arguments[_key];
|
12447
|
-
}
|
12448
|
-
_this = _BaseVideoParser.call.apply(_BaseVideoParser, [this].concat(args)) || this;
|
12449
|
-
_this.initVPS = null;
|
12450
|
-
return _this;
|
12021
|
+
var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
|
12022
|
+
_inheritsLoose(AvcVideoParser, _BaseVideoParser);
|
12023
|
+
function AvcVideoParser() {
|
12024
|
+
return _BaseVideoParser.apply(this, arguments) || this;
|
12451
12025
|
}
|
12452
|
-
var _proto =
|
12453
|
-
_proto.
|
12454
|
-
var
|
12455
|
-
var units = this.
|
12026
|
+
var _proto = AvcVideoParser.prototype;
|
12027
|
+
_proto.parseAVCPES = function parseAVCPES(track, textTrack, pes, last, duration) {
|
12028
|
+
var _this = this;
|
12029
|
+
var units = this.parseAVCNALu(track, pes.data);
|
12456
12030
|
var VideoSample = this.VideoSample;
|
12457
12031
|
var push;
|
12458
12032
|
var spsfound = false;
|
@@ -12468,143 +12042,112 @@
|
|
12468
12042
|
units.forEach(function (unit) {
|
12469
12043
|
var _VideoSample2;
|
12470
12044
|
switch (unit.type) {
|
12471
|
-
//
|
12472
|
-
case 0:
|
12045
|
+
// NDR
|
12473
12046
|
case 1:
|
12474
|
-
|
12475
|
-
|
12476
|
-
|
12477
|
-
|
12478
|
-
|
12479
|
-
|
12480
|
-
|
12481
|
-
|
12482
|
-
|
12483
|
-
|
12484
|
-
|
12485
|
-
|
12486
|
-
|
12487
|
-
|
12488
|
-
|
12489
|
-
|
12490
|
-
case 16:
|
12491
|
-
case 17:
|
12492
|
-
case 18:
|
12493
|
-
case 21:
|
12494
|
-
push = true;
|
12495
|
-
if (spsfound) {
|
12496
|
-
var _VideoSample;
|
12497
|
-
// handle PES not starting with AUD
|
12498
|
-
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12499
|
-
if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
|
12500
|
-
_this2.pushAccessUnit(VideoSample, track);
|
12501
|
-
VideoSample = _this2.VideoSample = null;
|
12047
|
+
{
|
12048
|
+
var iskey = false;
|
12049
|
+
push = true;
|
12050
|
+
var data = unit.data;
|
12051
|
+
// only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
|
12052
|
+
if (spsfound && data.length > 4) {
|
12053
|
+
// retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
|
12054
|
+
var sliceType = new ExpGolomb(data).readSliceType();
|
12055
|
+
// 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
|
12056
|
+
// SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
|
12057
|
+
// An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
|
12058
|
+
// I slice: A slice that is not an SI slice that is decoded using intra prediction only.
|
12059
|
+
// if (sliceType === 2 || sliceType === 7) {
|
12060
|
+
if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
|
12061
|
+
iskey = true;
|
12062
|
+
}
|
12502
12063
|
}
|
12064
|
+
if (iskey) {
|
12065
|
+
var _VideoSample;
|
12066
|
+
// if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
|
12067
|
+
if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
|
12068
|
+
_this.pushAccessUnit(VideoSample, track);
|
12069
|
+
VideoSample = _this.VideoSample = null;
|
12070
|
+
}
|
12071
|
+
}
|
12072
|
+
if (!VideoSample) {
|
12073
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
|
12074
|
+
}
|
12075
|
+
VideoSample.frame = true;
|
12076
|
+
VideoSample.key = iskey;
|
12077
|
+
break;
|
12078
|
+
// IDR
|
12503
12079
|
}
|
12504
|
-
|
12505
|
-
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12506
|
-
}
|
12507
|
-
VideoSample.key = true;
|
12508
|
-
VideoSample.frame = true;
|
12509
|
-
break;
|
12510
|
-
|
12511
|
-
// IDR
|
12512
|
-
case 19:
|
12513
|
-
case 20:
|
12080
|
+
case 5:
|
12514
12081
|
push = true;
|
12515
12082
|
// handle PES not starting with AUD
|
12516
12083
|
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12517
12084
|
if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
|
12518
|
-
|
12519
|
-
VideoSample =
|
12085
|
+
_this.pushAccessUnit(VideoSample, track);
|
12086
|
+
VideoSample = _this.VideoSample = null;
|
12520
12087
|
}
|
12521
12088
|
if (!VideoSample) {
|
12522
|
-
VideoSample =
|
12089
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
|
12523
12090
|
}
|
12524
12091
|
VideoSample.key = true;
|
12525
12092
|
VideoSample.frame = true;
|
12526
12093
|
break;
|
12527
|
-
|
12528
12094
|
// SEI
|
12529
|
-
case
|
12530
|
-
|
12531
|
-
|
12532
|
-
|
12533
|
-
|
12534
|
-
|
12535
|
-
|
12536
|
-
// VPS
|
12537
|
-
case 32:
|
12538
|
-
push = true;
|
12539
|
-
if (!track.vps) {
|
12540
|
-
var config = _this2.readVPS(unit.data);
|
12541
|
-
track.params = _objectSpread2({}, config);
|
12542
|
-
_this2.initVPS = unit.data;
|
12095
|
+
case 6:
|
12096
|
+
{
|
12097
|
+
push = true;
|
12098
|
+
parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
|
12099
|
+
break;
|
12100
|
+
// SPS
|
12543
12101
|
}
|
12544
|
-
|
12545
|
-
|
12546
|
-
|
12547
|
-
|
12548
|
-
|
12549
|
-
|
12550
|
-
|
12551
|
-
|
12552
|
-
if (track.
|
12553
|
-
|
12554
|
-
track.
|
12555
|
-
|
12556
|
-
|
12557
|
-
var _config = _this2.readSPS(unit.data);
|
12558
|
-
track.width = _config.width;
|
12559
|
-
track.height = _config.height;
|
12560
|
-
track.pixelRatio = _config.pixelRatio;
|
12102
|
+
case 7:
|
12103
|
+
{
|
12104
|
+
var _track$pixelRatio, _track$pixelRatio2;
|
12105
|
+
push = true;
|
12106
|
+
spsfound = true;
|
12107
|
+
var sps = unit.data;
|
12108
|
+
var expGolombDecoder = new ExpGolomb(sps);
|
12109
|
+
var config = expGolombDecoder.readSPS();
|
12110
|
+
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]) {
|
12111
|
+
track.width = config.width;
|
12112
|
+
track.height = config.height;
|
12113
|
+
track.pixelRatio = config.pixelRatio;
|
12114
|
+
track.sps = [sps];
|
12561
12115
|
track.duration = duration;
|
12562
|
-
|
12563
|
-
|
12564
|
-
for (var
|
12565
|
-
|
12116
|
+
var codecarray = sps.subarray(1, 4);
|
12117
|
+
var codecstring = 'avc1.';
|
12118
|
+
for (var i = 0; i < 3; i++) {
|
12119
|
+
var h = codecarray[i].toString(16);
|
12120
|
+
if (h.length < 2) {
|
12121
|
+
h = '0' + h;
|
12122
|
+
}
|
12123
|
+
codecstring += h;
|
12566
12124
|
}
|
12125
|
+
track.codec = codecstring;
|
12567
12126
|
}
|
12568
|
-
|
12569
|
-
track.sps.push(unit.data);
|
12570
|
-
}
|
12571
|
-
}
|
12572
|
-
if (!VideoSample) {
|
12573
|
-
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12127
|
+
break;
|
12574
12128
|
}
|
12575
|
-
VideoSample.key = true;
|
12576
|
-
break;
|
12577
|
-
|
12578
12129
|
// PPS
|
12579
|
-
case
|
12130
|
+
case 8:
|
12580
12131
|
push = true;
|
12581
|
-
|
12582
|
-
if (!track.pps) {
|
12583
|
-
track.pps = [];
|
12584
|
-
var _config2 = _this2.readPPS(unit.data);
|
12585
|
-
for (var _prop in _config2) {
|
12586
|
-
track.params[_prop] = _config2[_prop];
|
12587
|
-
}
|
12588
|
-
}
|
12589
|
-
if (_this2.initVPS !== null || track.pps.length === 0) {
|
12590
|
-
track.pps.push(unit.data);
|
12591
|
-
}
|
12592
|
-
}
|
12132
|
+
track.pps = [unit.data];
|
12593
12133
|
break;
|
12594
|
-
|
12595
|
-
|
12596
|
-
case 35:
|
12134
|
+
// AUD
|
12135
|
+
case 9:
|
12597
12136
|
push = true;
|
12598
12137
|
track.audFound = true;
|
12599
12138
|
if (VideoSample) {
|
12600
|
-
|
12139
|
+
_this.pushAccessUnit(VideoSample, track);
|
12601
12140
|
}
|
12602
|
-
VideoSample =
|
12141
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
|
12142
|
+
break;
|
12143
|
+
// Filler Data
|
12144
|
+
case 12:
|
12145
|
+
push = true;
|
12603
12146
|
break;
|
12604
12147
|
default:
|
12605
12148
|
push = false;
|
12606
12149
|
if (VideoSample) {
|
12607
|
-
VideoSample.debug += 'unknown
|
12150
|
+
VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
|
12608
12151
|
}
|
12609
12152
|
break;
|
12610
12153
|
}
|
@@ -12619,425 +12162,111 @@
|
|
12619
12162
|
this.VideoSample = null;
|
12620
12163
|
}
|
12621
12164
|
};
|
12622
|
-
_proto.
|
12623
|
-
|
12624
|
-
|
12625
|
-
|
12626
|
-
var
|
12627
|
-
var
|
12628
|
-
|
12629
|
-
|
12630
|
-
|
12631
|
-
|
12632
|
-
|
12633
|
-
|
12634
|
-
}
|
12635
|
-
dst[dstIdx] = arr[i];
|
12636
|
-
dstIdx++;
|
12637
|
-
}
|
12638
|
-
return new Uint8Array(dst.buffer, 0, dstIdx);
|
12639
|
-
};
|
12640
|
-
_proto.readVPS = function readVPS(vps) {
|
12641
|
-
var eg = new ExpGolomb(vps);
|
12642
|
-
// remove header
|
12643
|
-
eg.readUByte();
|
12644
|
-
eg.readUByte();
|
12645
|
-
eg.readBits(4); // video_parameter_set_id
|
12646
|
-
eg.skipBits(2);
|
12647
|
-
eg.readBits(6); // max_layers_minus1
|
12648
|
-
var max_sub_layers_minus1 = eg.readBits(3);
|
12649
|
-
var temporal_id_nesting_flag = eg.readBoolean();
|
12650
|
-
// ...vui fps can be here, but empty fps value is not critical for metadata
|
12165
|
+
_proto.parseAVCNALu = function parseAVCNALu(track, array) {
|
12166
|
+
var len = array.byteLength;
|
12167
|
+
var state = track.naluState || 0;
|
12168
|
+
var lastState = state;
|
12169
|
+
var units = [];
|
12170
|
+
var i = 0;
|
12171
|
+
var value;
|
12172
|
+
var overflow;
|
12173
|
+
var unitType;
|
12174
|
+
var lastUnitStart = -1;
|
12175
|
+
var lastUnitType = 0;
|
12176
|
+
// logger.log('PES:' + Hex.hexDump(array));
|
12651
12177
|
|
12652
|
-
|
12653
|
-
|
12654
|
-
|
12655
|
-
|
12656
|
-
|
12657
|
-
|
12658
|
-
|
12659
|
-
eg.readUByte();
|
12660
|
-
eg.readUByte();
|
12661
|
-
eg.readBits(4); //video_parameter_set_id
|
12662
|
-
var max_sub_layers_minus1 = eg.readBits(3);
|
12663
|
-
eg.readBoolean(); // temporal_id_nesting_flag
|
12664
|
-
|
12665
|
-
// profile_tier_level
|
12666
|
-
var general_profile_space = eg.readBits(2);
|
12667
|
-
var general_tier_flag = eg.readBoolean();
|
12668
|
-
var general_profile_idc = eg.readBits(5);
|
12669
|
-
var general_profile_compatibility_flags_1 = eg.readUByte();
|
12670
|
-
var general_profile_compatibility_flags_2 = eg.readUByte();
|
12671
|
-
var general_profile_compatibility_flags_3 = eg.readUByte();
|
12672
|
-
var general_profile_compatibility_flags_4 = eg.readUByte();
|
12673
|
-
var general_constraint_indicator_flags_1 = eg.readUByte();
|
12674
|
-
var general_constraint_indicator_flags_2 = eg.readUByte();
|
12675
|
-
var general_constraint_indicator_flags_3 = eg.readUByte();
|
12676
|
-
var general_constraint_indicator_flags_4 = eg.readUByte();
|
12677
|
-
var general_constraint_indicator_flags_5 = eg.readUByte();
|
12678
|
-
var general_constraint_indicator_flags_6 = eg.readUByte();
|
12679
|
-
var general_level_idc = eg.readUByte();
|
12680
|
-
var sub_layer_profile_present_flags = [];
|
12681
|
-
var sub_layer_level_present_flags = [];
|
12682
|
-
for (var i = 0; i < max_sub_layers_minus1; i++) {
|
12683
|
-
sub_layer_profile_present_flags.push(eg.readBoolean());
|
12684
|
-
sub_layer_level_present_flags.push(eg.readBoolean());
|
12685
|
-
}
|
12686
|
-
if (max_sub_layers_minus1 > 0) {
|
12687
|
-
for (var _i = max_sub_layers_minus1; _i < 8; _i++) {
|
12688
|
-
eg.readBits(2);
|
12689
|
-
}
|
12690
|
-
}
|
12691
|
-
for (var _i2 = 0; _i2 < max_sub_layers_minus1; _i2++) {
|
12692
|
-
if (sub_layer_profile_present_flags[_i2]) {
|
12693
|
-
eg.readUByte(); // sub_layer_profile_space, sub_layer_tier_flag, sub_layer_profile_idc
|
12694
|
-
eg.readUByte();
|
12695
|
-
eg.readUByte();
|
12696
|
-
eg.readUByte();
|
12697
|
-
eg.readUByte(); // sub_layer_profile_compatibility_flag
|
12698
|
-
eg.readUByte();
|
12699
|
-
eg.readUByte();
|
12700
|
-
eg.readUByte();
|
12701
|
-
eg.readUByte();
|
12702
|
-
eg.readUByte();
|
12703
|
-
eg.readUByte();
|
12704
|
-
}
|
12705
|
-
if (sub_layer_level_present_flags[_i2]) {
|
12706
|
-
eg.readUByte();
|
12707
|
-
}
|
12708
|
-
}
|
12709
|
-
eg.readUEG(); // seq_parameter_set_id
|
12710
|
-
var chroma_format_idc = eg.readUEG();
|
12711
|
-
if (chroma_format_idc == 3) {
|
12712
|
-
eg.skipBits(1); //separate_colour_plane_flag
|
12713
|
-
}
|
12714
|
-
var pic_width_in_luma_samples = eg.readUEG();
|
12715
|
-
var pic_height_in_luma_samples = eg.readUEG();
|
12716
|
-
var conformance_window_flag = eg.readBoolean();
|
12717
|
-
var pic_left_offset = 0,
|
12718
|
-
pic_right_offset = 0,
|
12719
|
-
pic_top_offset = 0,
|
12720
|
-
pic_bottom_offset = 0;
|
12721
|
-
if (conformance_window_flag) {
|
12722
|
-
pic_left_offset += eg.readUEG();
|
12723
|
-
pic_right_offset += eg.readUEG();
|
12724
|
-
pic_top_offset += eg.readUEG();
|
12725
|
-
pic_bottom_offset += eg.readUEG();
|
12726
|
-
}
|
12727
|
-
var bit_depth_luma_minus8 = eg.readUEG();
|
12728
|
-
var bit_depth_chroma_minus8 = eg.readUEG();
|
12729
|
-
var log2_max_pic_order_cnt_lsb_minus4 = eg.readUEG();
|
12730
|
-
var sub_layer_ordering_info_present_flag = eg.readBoolean();
|
12731
|
-
for (var _i3 = sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; _i3 <= max_sub_layers_minus1; _i3++) {
|
12732
|
-
eg.skipUEG(); // max_dec_pic_buffering_minus1[i]
|
12733
|
-
eg.skipUEG(); // max_num_reorder_pics[i]
|
12734
|
-
eg.skipUEG(); // max_latency_increase_plus1[i]
|
12735
|
-
}
|
12736
|
-
eg.skipUEG(); // log2_min_luma_coding_block_size_minus3
|
12737
|
-
eg.skipUEG(); // log2_diff_max_min_luma_coding_block_size
|
12738
|
-
eg.skipUEG(); // log2_min_transform_block_size_minus2
|
12739
|
-
eg.skipUEG(); // log2_diff_max_min_transform_block_size
|
12740
|
-
eg.skipUEG(); // max_transform_hierarchy_depth_inter
|
12741
|
-
eg.skipUEG(); // max_transform_hierarchy_depth_intra
|
12742
|
-
var scaling_list_enabled_flag = eg.readBoolean();
|
12743
|
-
if (scaling_list_enabled_flag) {
|
12744
|
-
var sps_scaling_list_data_present_flag = eg.readBoolean();
|
12745
|
-
if (sps_scaling_list_data_present_flag) {
|
12746
|
-
for (var sizeId = 0; sizeId < 4; sizeId++) {
|
12747
|
-
for (var matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
|
12748
|
-
var scaling_list_pred_mode_flag = eg.readBoolean();
|
12749
|
-
if (!scaling_list_pred_mode_flag) {
|
12750
|
-
eg.readUEG(); // scaling_list_pred_matrix_id_delta
|
12751
|
-
} else {
|
12752
|
-
var coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
|
12753
|
-
if (sizeId > 1) {
|
12754
|
-
eg.readEG();
|
12755
|
-
}
|
12756
|
-
for (var _i4 = 0; _i4 < coefNum; _i4++) {
|
12757
|
-
eg.readEG();
|
12758
|
-
}
|
12759
|
-
}
|
12760
|
-
}
|
12761
|
-
}
|
12762
|
-
}
|
12178
|
+
if (state === -1) {
|
12179
|
+
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
12180
|
+
lastUnitStart = 0;
|
12181
|
+
// NALu type is value read from offset 0
|
12182
|
+
lastUnitType = array[0] & 0x1f;
|
12183
|
+
state = 0;
|
12184
|
+
i = 1;
|
12763
12185
|
}
|
12764
|
-
|
12765
|
-
|
12766
|
-
|
12767
|
-
|
12768
|
-
|
12769
|
-
|
12770
|
-
|
12771
|
-
|
12772
|
-
|
12773
|
-
|
12774
|
-
|
12775
|
-
|
12776
|
-
|
12777
|
-
|
12778
|
-
|
12779
|
-
|
12780
|
-
|
12781
|
-
|
12782
|
-
|
12783
|
-
|
12784
|
-
|
12785
|
-
|
12786
|
-
|
12787
|
-
|
12788
|
-
|
12789
|
-
|
12790
|
-
|
12791
|
-
|
12792
|
-
|
12793
|
-
if (
|
12794
|
-
|
12795
|
-
|
12796
|
-
|
12797
|
-
|
12798
|
-
|
12799
|
-
|
12800
|
-
|
12801
|
-
num_delta_pocs = num_negative_pics + num_positive_pics;
|
12802
|
-
for (var _j = 0; _j < num_negative_pics; _j++) {
|
12803
|
-
eg.readUEG();
|
12804
|
-
eg.readBoolean();
|
12805
|
-
}
|
12806
|
-
for (var _j2 = 0; _j2 < num_positive_pics; _j2++) {
|
12807
|
-
eg.readUEG();
|
12808
|
-
eg.readBoolean();
|
12809
|
-
}
|
12810
|
-
}
|
12811
|
-
}
|
12812
|
-
var long_term_ref_pics_present_flag = eg.readBoolean();
|
12813
|
-
if (long_term_ref_pics_present_flag) {
|
12814
|
-
var num_long_term_ref_pics_sps = eg.readUEG();
|
12815
|
-
for (var _i6 = 0; _i6 < num_long_term_ref_pics_sps; _i6++) {
|
12816
|
-
for (var _j3 = 0; _j3 < log2_max_pic_order_cnt_lsb_minus4 + 4; _j3++) {
|
12817
|
-
eg.readBits(1);
|
12818
|
-
}
|
12819
|
-
eg.readBits(1);
|
12820
|
-
}
|
12821
|
-
}
|
12822
|
-
var min_spatial_segmentation_idc = 0;
|
12823
|
-
var sar_width = 1,
|
12824
|
-
sar_height = 1;
|
12825
|
-
var fps_fixed = true,
|
12826
|
-
fps_den = 1,
|
12827
|
-
fps_num = 0;
|
12828
|
-
eg.readBoolean(); // sps_temporal_mvp_enabled_flag
|
12829
|
-
eg.readBoolean(); // strong_intra_smoothing_enabled_flag
|
12830
|
-
var default_display_window_flag = false;
|
12831
|
-
var vui_parameters_present_flag = eg.readBoolean();
|
12832
|
-
if (vui_parameters_present_flag) {
|
12833
|
-
var aspect_ratio_info_present_flag = eg.readBoolean();
|
12834
|
-
if (aspect_ratio_info_present_flag) {
|
12835
|
-
var aspect_ratio_idc = eg.readUByte();
|
12836
|
-
var sar_width_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
|
12837
|
-
var sar_height_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
|
12838
|
-
if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
|
12839
|
-
sar_width = sar_width_table[aspect_ratio_idc - 1];
|
12840
|
-
sar_height = sar_height_table[aspect_ratio_idc - 1];
|
12841
|
-
} else if (aspect_ratio_idc === 255) {
|
12842
|
-
sar_width = eg.readBits(16);
|
12843
|
-
sar_height = eg.readBits(16);
|
12844
|
-
}
|
12845
|
-
}
|
12846
|
-
var overscan_info_present_flag = eg.readBoolean();
|
12847
|
-
if (overscan_info_present_flag) {
|
12848
|
-
eg.readBoolean();
|
12849
|
-
}
|
12850
|
-
var video_signal_type_present_flag = eg.readBoolean();
|
12851
|
-
if (video_signal_type_present_flag) {
|
12852
|
-
eg.readBits(3);
|
12853
|
-
eg.readBoolean();
|
12854
|
-
var colour_description_present_flag = eg.readBoolean();
|
12855
|
-
if (colour_description_present_flag) {
|
12856
|
-
eg.readUByte();
|
12857
|
-
eg.readUByte();
|
12858
|
-
eg.readUByte();
|
12859
|
-
}
|
12860
|
-
}
|
12861
|
-
var chroma_loc_info_present_flag = eg.readBoolean();
|
12862
|
-
if (chroma_loc_info_present_flag) {
|
12863
|
-
eg.readUEG();
|
12864
|
-
eg.readUEG();
|
12865
|
-
}
|
12866
|
-
eg.readBoolean(); // neutral_chroma_indication_flag
|
12867
|
-
eg.readBoolean(); // field_seq_flag
|
12868
|
-
eg.readBoolean(); // frame_field_info_present_flag
|
12869
|
-
default_display_window_flag = eg.readBoolean();
|
12870
|
-
if (default_display_window_flag) {
|
12871
|
-
pic_left_offset += eg.readUEG();
|
12872
|
-
pic_right_offset += eg.readUEG();
|
12873
|
-
pic_top_offset += eg.readUEG();
|
12874
|
-
pic_bottom_offset += eg.readUEG();
|
12875
|
-
}
|
12876
|
-
var vui_timing_info_present_flag = eg.readBoolean();
|
12877
|
-
if (vui_timing_info_present_flag) {
|
12878
|
-
fps_den = eg.readBits(32);
|
12879
|
-
fps_num = eg.readBits(32);
|
12880
|
-
var vui_poc_proportional_to_timing_flag = eg.readBoolean();
|
12881
|
-
if (vui_poc_proportional_to_timing_flag) {
|
12882
|
-
eg.readUEG();
|
12883
|
-
}
|
12884
|
-
var vui_hrd_parameters_present_flag = eg.readBoolean();
|
12885
|
-
if (vui_hrd_parameters_present_flag) {
|
12886
|
-
//const commonInfPresentFlag = true;
|
12887
|
-
//if (commonInfPresentFlag) {
|
12888
|
-
var nal_hrd_parameters_present_flag = eg.readBoolean();
|
12889
|
-
var vcl_hrd_parameters_present_flag = eg.readBoolean();
|
12890
|
-
var sub_pic_hrd_params_present_flag = false;
|
12891
|
-
if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
|
12892
|
-
sub_pic_hrd_params_present_flag = eg.readBoolean();
|
12893
|
-
if (sub_pic_hrd_params_present_flag) {
|
12894
|
-
eg.readUByte();
|
12895
|
-
eg.readBits(5);
|
12896
|
-
eg.readBoolean();
|
12897
|
-
eg.readBits(5);
|
12898
|
-
}
|
12899
|
-
eg.readBits(4); // bit_rate_scale
|
12900
|
-
eg.readBits(4); // cpb_size_scale
|
12901
|
-
if (sub_pic_hrd_params_present_flag) {
|
12902
|
-
eg.readBits(4);
|
12903
|
-
}
|
12904
|
-
eg.readBits(5);
|
12905
|
-
eg.readBits(5);
|
12906
|
-
eg.readBits(5);
|
12907
|
-
}
|
12908
|
-
//}
|
12909
|
-
for (var _i7 = 0; _i7 <= max_sub_layers_minus1; _i7++) {
|
12910
|
-
fps_fixed = eg.readBoolean(); // fixed_pic_rate_general_flag
|
12911
|
-
var fixed_pic_rate_within_cvs_flag = fps_fixed || eg.readBoolean();
|
12912
|
-
var low_delay_hrd_flag = false;
|
12913
|
-
if (fixed_pic_rate_within_cvs_flag) {
|
12914
|
-
eg.readEG();
|
12915
|
-
} else {
|
12916
|
-
low_delay_hrd_flag = eg.readBoolean();
|
12917
|
-
}
|
12918
|
-
var cpb_cnt = low_delay_hrd_flag ? 1 : eg.readUEG() + 1;
|
12919
|
-
if (nal_hrd_parameters_present_flag) {
|
12920
|
-
for (var _j4 = 0; _j4 < cpb_cnt; _j4++) {
|
12921
|
-
eg.readUEG();
|
12922
|
-
eg.readUEG();
|
12923
|
-
if (sub_pic_hrd_params_present_flag) {
|
12924
|
-
eg.readUEG();
|
12925
|
-
eg.readUEG();
|
12926
|
-
}
|
12927
|
-
eg.skipBits(1);
|
12186
|
+
while (i < len) {
|
12187
|
+
value = array[i++];
|
12188
|
+
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
12189
|
+
if (!state) {
|
12190
|
+
state = value ? 0 : 1;
|
12191
|
+
continue;
|
12192
|
+
}
|
12193
|
+
if (state === 1) {
|
12194
|
+
state = value ? 0 : 2;
|
12195
|
+
continue;
|
12196
|
+
}
|
12197
|
+
// here we have state either equal to 2 or 3
|
12198
|
+
if (!value) {
|
12199
|
+
state = 3;
|
12200
|
+
} else if (value === 1) {
|
12201
|
+
overflow = i - state - 1;
|
12202
|
+
if (lastUnitStart >= 0) {
|
12203
|
+
var unit = {
|
12204
|
+
data: array.subarray(lastUnitStart, overflow),
|
12205
|
+
type: lastUnitType
|
12206
|
+
};
|
12207
|
+
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
|
12208
|
+
units.push(unit);
|
12209
|
+
} else {
|
12210
|
+
// lastUnitStart is undefined => this is the first start code found in this PES packet
|
12211
|
+
// first check if start code delimiter is overlapping between 2 PES packets,
|
12212
|
+
// ie it started in last packet (lastState not zero)
|
12213
|
+
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
12214
|
+
var lastUnit = this.getLastNalUnit(track.samples);
|
12215
|
+
if (lastUnit) {
|
12216
|
+
if (lastState && i <= 4 - lastState) {
|
12217
|
+
// start delimiter overlapping between PES packets
|
12218
|
+
// strip start delimiter bytes from the end of last NAL unit
|
12219
|
+
// check if lastUnit had a state different from zero
|
12220
|
+
if (lastUnit.state) {
|
12221
|
+
// strip last bytes
|
12222
|
+
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
|
12928
12223
|
}
|
12929
12224
|
}
|
12930
|
-
|
12931
|
-
|
12932
|
-
|
12933
|
-
|
12934
|
-
|
12935
|
-
|
12936
|
-
eg.readUEG();
|
12937
|
-
}
|
12938
|
-
eg.skipBits(1);
|
12939
|
-
}
|
12225
|
+
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
|
12226
|
+
|
12227
|
+
if (overflow > 0) {
|
12228
|
+
// logger.log('first NALU found with overflow:' + overflow);
|
12229
|
+
lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
|
12230
|
+
lastUnit.state = 0;
|
12940
12231
|
}
|
12941
12232
|
}
|
12942
12233
|
}
|
12943
|
-
|
12944
|
-
|
12945
|
-
|
12946
|
-
|
12947
|
-
|
12948
|
-
|
12949
|
-
|
12950
|
-
|
12951
|
-
|
12952
|
-
|
12953
|
-
height = pic_height_in_luma_samples;
|
12954
|
-
if (conformance_window_flag || default_display_window_flag) {
|
12955
|
-
var chroma_scale_w = 1,
|
12956
|
-
chroma_scale_h = 1;
|
12957
|
-
if (chroma_format_idc === 1) {
|
12958
|
-
// YUV 420
|
12959
|
-
chroma_scale_w = chroma_scale_h = 2;
|
12960
|
-
} else if (chroma_format_idc == 2) {
|
12961
|
-
// YUV 422
|
12962
|
-
chroma_scale_w = 2;
|
12963
|
-
}
|
12964
|
-
width = pic_width_in_luma_samples - chroma_scale_w * pic_right_offset - chroma_scale_w * pic_left_offset;
|
12965
|
-
height = pic_height_in_luma_samples - chroma_scale_h * pic_bottom_offset - chroma_scale_h * pic_top_offset;
|
12966
|
-
}
|
12967
|
-
var profile_space_string = general_profile_space ? ['A', 'B', 'C'][general_profile_space] : '';
|
12968
|
-
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;
|
12969
|
-
var profile_compatibility_rev = 0;
|
12970
|
-
for (var _i8 = 0; _i8 < 32; _i8++) {
|
12971
|
-
profile_compatibility_rev = (profile_compatibility_rev | (profile_compatibility_buf >> _i8 & 1) << 31 - _i8) >>> 0; // reverse bit position (and cast as UInt32)
|
12972
|
-
}
|
12973
|
-
var profile_compatibility_flags_string = profile_compatibility_rev.toString(16);
|
12974
|
-
if (general_profile_idc === 1 && profile_compatibility_flags_string === '2') {
|
12975
|
-
profile_compatibility_flags_string = '6';
|
12976
|
-
}
|
12977
|
-
var tier_flag_string = general_tier_flag ? 'H' : 'L';
|
12978
|
-
return {
|
12979
|
-
codecString: "hvc1." + profile_space_string + general_profile_idc + "." + profile_compatibility_flags_string + "." + tier_flag_string + general_level_idc + ".B0",
|
12980
|
-
params: {
|
12981
|
-
general_tier_flag: general_tier_flag,
|
12982
|
-
general_profile_idc: general_profile_idc,
|
12983
|
-
general_profile_space: general_profile_space,
|
12984
|
-
general_profile_compatibility_flags: [general_profile_compatibility_flags_1, general_profile_compatibility_flags_2, general_profile_compatibility_flags_3, general_profile_compatibility_flags_4],
|
12985
|
-
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],
|
12986
|
-
general_level_idc: general_level_idc,
|
12987
|
-
bit_depth: bit_depth_luma_minus8 + 8,
|
12988
|
-
bit_depth_luma_minus8: bit_depth_luma_minus8,
|
12989
|
-
bit_depth_chroma_minus8: bit_depth_chroma_minus8,
|
12990
|
-
min_spatial_segmentation_idc: min_spatial_segmentation_idc,
|
12991
|
-
chroma_format_idc: chroma_format_idc,
|
12992
|
-
frame_rate: {
|
12993
|
-
fixed: fps_fixed,
|
12994
|
-
fps: fps_num / fps_den
|
12234
|
+
// check if we can read unit type
|
12235
|
+
if (i < len) {
|
12236
|
+
unitType = array[i] & 0x1f;
|
12237
|
+
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
12238
|
+
lastUnitStart = i;
|
12239
|
+
lastUnitType = unitType;
|
12240
|
+
state = 0;
|
12241
|
+
} else {
|
12242
|
+
// not enough byte to read unit type. let's read it on next PES parsing
|
12243
|
+
state = -1;
|
12995
12244
|
}
|
12996
|
-
}
|
12997
|
-
|
12998
|
-
|
12999
|
-
pixelRatio: [sar_width, sar_height]
|
13000
|
-
};
|
13001
|
-
};
|
13002
|
-
_proto.readPPS = function readPPS(pps) {
|
13003
|
-
var eg = new ExpGolomb(this.ebsp2rbsp(pps));
|
13004
|
-
eg.readUByte();
|
13005
|
-
eg.readUByte();
|
13006
|
-
eg.skipUEG(); // pic_parameter_set_id
|
13007
|
-
eg.skipUEG(); // seq_parameter_set_id
|
13008
|
-
eg.skipBits(2); // dependent_slice_segments_enabled_flag, output_flag_present_flag
|
13009
|
-
eg.skipBits(3); // num_extra_slice_header_bits
|
13010
|
-
eg.skipBits(2); // sign_data_hiding_enabled_flag, cabac_init_present_flag
|
13011
|
-
eg.skipUEG();
|
13012
|
-
eg.skipUEG();
|
13013
|
-
eg.skipEG(); // init_qp_minus26
|
13014
|
-
eg.skipBits(2); // constrained_intra_pred_flag, transform_skip_enabled_flag
|
13015
|
-
var cu_qp_delta_enabled_flag = eg.readBoolean();
|
13016
|
-
if (cu_qp_delta_enabled_flag) {
|
13017
|
-
eg.skipUEG();
|
13018
|
-
}
|
13019
|
-
eg.skipEG(); // cb_qp_offset
|
13020
|
-
eg.skipEG(); // cr_qp_offset
|
13021
|
-
eg.skipBits(4); // pps_slice_chroma_qp_offsets_present_flag, weighted_pred_flag, weighted_bipred_flag, transquant_bypass_enabled_flag
|
13022
|
-
var tiles_enabled_flag = eg.readBoolean();
|
13023
|
-
var entropy_coding_sync_enabled_flag = eg.readBoolean();
|
13024
|
-
var parallelismType = 1; // slice-based parallel decoding
|
13025
|
-
if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) {
|
13026
|
-
parallelismType = 0; // mixed-type parallel decoding
|
13027
|
-
} else if (entropy_coding_sync_enabled_flag) {
|
13028
|
-
parallelismType = 3; // wavefront-based parallel decoding
|
13029
|
-
} else if (tiles_enabled_flag) {
|
13030
|
-
parallelismType = 2; // tile-based parallel decoding
|
12245
|
+
} else {
|
12246
|
+
state = 0;
|
12247
|
+
}
|
13031
12248
|
}
|
13032
|
-
|
13033
|
-
|
13034
|
-
|
13035
|
-
|
13036
|
-
|
13037
|
-
|
13038
|
-
|
12249
|
+
if (lastUnitStart >= 0 && state >= 0) {
|
12250
|
+
var _unit = {
|
12251
|
+
data: array.subarray(lastUnitStart, len),
|
12252
|
+
type: lastUnitType,
|
12253
|
+
state: state
|
12254
|
+
};
|
12255
|
+
units.push(_unit);
|
12256
|
+
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
12257
|
+
}
|
12258
|
+
// no NALu found
|
12259
|
+
if (units.length === 0) {
|
12260
|
+
// append pes.data to previous NAL unit
|
12261
|
+
var _lastUnit = this.getLastNalUnit(track.samples);
|
12262
|
+
if (_lastUnit) {
|
12263
|
+
_lastUnit.data = appendUint8Array(_lastUnit.data, array);
|
12264
|
+
}
|
12265
|
+
}
|
12266
|
+
track.naluState = state;
|
12267
|
+
return units;
|
13039
12268
|
};
|
13040
|
-
return
|
12269
|
+
return AvcVideoParser;
|
13041
12270
|
}(BaseVideoParser);
|
13042
12271
|
|
13043
12272
|
/**
|
@@ -13055,7 +12284,7 @@
|
|
13055
12284
|
}
|
13056
12285
|
var _proto = SampleAesDecrypter.prototype;
|
13057
12286
|
_proto.decryptBuffer = function decryptBuffer(encryptedData) {
|
13058
|
-
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer
|
12287
|
+
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
|
13059
12288
|
}
|
13060
12289
|
|
13061
12290
|
// AAC - encrypt all full 16 bytes blocks starting from offset 16
|
@@ -13174,7 +12403,7 @@
|
|
13174
12403
|
this.observer = observer;
|
13175
12404
|
this.config = config;
|
13176
12405
|
this.typeSupported = typeSupported;
|
13177
|
-
this.videoParser =
|
12406
|
+
this.videoParser = new AvcVideoParser();
|
13178
12407
|
}
|
13179
12408
|
TSDemuxer.probe = function probe(data) {
|
13180
12409
|
var syncOffset = TSDemuxer.syncOffset(data);
|
@@ -13344,21 +12573,7 @@
|
|
13344
12573
|
case videoPid:
|
13345
12574
|
if (stt) {
|
13346
12575
|
if (videoData && (pes = parsePES(videoData))) {
|
13347
|
-
|
13348
|
-
switch (videoTrack.segmentCodec) {
|
13349
|
-
case 'avc':
|
13350
|
-
this.videoParser = new AvcVideoParser();
|
13351
|
-
break;
|
13352
|
-
case 'hevc':
|
13353
|
-
{
|
13354
|
-
this.videoParser = new HevcVideoParser();
|
13355
|
-
}
|
13356
|
-
break;
|
13357
|
-
}
|
13358
|
-
}
|
13359
|
-
if (this.videoParser !== null) {
|
13360
|
-
this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
|
13361
|
-
}
|
12576
|
+
this.videoParser.parseAVCPES(videoTrack, textTrack, pes, false, this._duration);
|
13362
12577
|
}
|
13363
12578
|
videoData = {
|
13364
12579
|
data: [],
|
@@ -13515,28 +12730,14 @@
|
|
13515
12730
|
videoTrack = demuxResult.videoTrack,
|
13516
12731
|
id3Track = demuxResult.id3Track,
|
13517
12732
|
textTrack = demuxResult.textTrack;
|
13518
|
-
var videoData = videoTrack.pesData;
|
13519
|
-
var audioData = audioTrack.pesData;
|
13520
|
-
var id3Data = id3Track.pesData;
|
13521
|
-
// try to parse last PES packets
|
13522
|
-
var pes;
|
13523
|
-
if (videoData && (pes = parsePES(videoData))) {
|
13524
|
-
|
13525
|
-
|
13526
|
-
case 'avc':
|
13527
|
-
this.videoParser = new AvcVideoParser();
|
13528
|
-
break;
|
13529
|
-
case 'hevc':
|
13530
|
-
{
|
13531
|
-
this.videoParser = new HevcVideoParser();
|
13532
|
-
}
|
13533
|
-
break;
|
13534
|
-
}
|
13535
|
-
}
|
13536
|
-
if (this.videoParser !== null) {
|
13537
|
-
this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
|
13538
|
-
videoTrack.pesData = null;
|
13539
|
-
}
|
12733
|
+
var videoData = videoTrack.pesData;
|
12734
|
+
var audioData = audioTrack.pesData;
|
12735
|
+
var id3Data = id3Track.pesData;
|
12736
|
+
// try to parse last PES packets
|
12737
|
+
var pes;
|
12738
|
+
if (videoData && (pes = parsePES(videoData))) {
|
12739
|
+
this.videoParser.parseAVCPES(videoTrack, textTrack, pes, true, this._duration);
|
12740
|
+
videoTrack.pesData = null;
|
13540
12741
|
} else {
|
13541
12742
|
// either avcData null or PES truncated, keep it for next frag parsing
|
13542
12743
|
videoTrack.pesData = videoData;
|
@@ -13868,14 +13069,7 @@
|
|
13868
13069
|
logger.warn('Unsupported EC-3 in M2TS found');
|
13869
13070
|
break;
|
13870
13071
|
case 0x24:
|
13871
|
-
|
13872
|
-
{
|
13873
|
-
if (result.videoPid === -1) {
|
13874
|
-
result.videoPid = pid;
|
13875
|
-
result.segmentVideoCodec = 'hevc';
|
13876
|
-
logger.log('HEVC in M2TS found');
|
13877
|
-
}
|
13878
|
-
}
|
13072
|
+
logger.warn('Unsupported HEVC in M2TS found');
|
13879
13073
|
break;
|
13880
13074
|
}
|
13881
13075
|
// move to the next table entry
|
@@ -14103,8 +13297,6 @@
|
|
14103
13297
|
avc1: [],
|
14104
13298
|
// codingname
|
14105
13299
|
avcC: [],
|
14106
|
-
hvc1: [],
|
14107
|
-
hvcC: [],
|
14108
13300
|
btrt: [],
|
14109
13301
|
dinf: [],
|
14110
13302
|
dref: [],
|
@@ -14532,10 +13724,8 @@
|
|
14532
13724
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
14533
13725
|
}
|
14534
13726
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
14535
|
-
} else if (track.segmentCodec === 'avc') {
|
14536
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
14537
13727
|
} else {
|
14538
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.
|
13728
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
14539
13729
|
}
|
14540
13730
|
};
|
14541
13731
|
MP4.tkhd = function tkhd(track) {
|
@@ -14673,84 +13863,6 @@
|
|
14673
13863
|
var result = appendUint8Array(MP4.FTYP, movie);
|
14674
13864
|
return result;
|
14675
13865
|
};
|
14676
|
-
MP4.hvc1 = function hvc1(track) {
|
14677
|
-
var ps = track.params;
|
14678
|
-
var units = [track.vps, track.sps, track.pps];
|
14679
|
-
var NALuLengthSize = 4;
|
14680
|
-
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]);
|
14681
|
-
|
14682
|
-
// compute hvcC size in bytes
|
14683
|
-
var length = config.length;
|
14684
|
-
for (var i = 0; i < units.length; i += 1) {
|
14685
|
-
length += 3;
|
14686
|
-
for (var j = 0; j < units[i].length; j += 1) {
|
14687
|
-
length += 2 + units[i][j].length;
|
14688
|
-
}
|
14689
|
-
}
|
14690
|
-
var hvcC = new Uint8Array(length);
|
14691
|
-
hvcC.set(config, 0);
|
14692
|
-
length = config.length;
|
14693
|
-
// append parameter set units: one vps, one or more sps and pps
|
14694
|
-
var iMax = units.length - 1;
|
14695
|
-
for (var _i = 0; _i < units.length; _i += 1) {
|
14696
|
-
hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
|
14697
|
-
length += 3;
|
14698
|
-
for (var _j = 0; _j < units[_i].length; _j += 1) {
|
14699
|
-
hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
|
14700
|
-
length += 2;
|
14701
|
-
hvcC.set(units[_i][_j], length);
|
14702
|
-
length += units[_i][_j].length;
|
14703
|
-
}
|
14704
|
-
}
|
14705
|
-
var hvcc = MP4.box(MP4.types.hvcC, hvcC);
|
14706
|
-
var width = track.width;
|
14707
|
-
var height = track.height;
|
14708
|
-
var hSpacing = track.pixelRatio[0];
|
14709
|
-
var vSpacing = track.pixelRatio[1];
|
14710
|
-
return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
|
14711
|
-
// reserved
|
14712
|
-
0x00, 0x00, 0x00,
|
14713
|
-
// reserved
|
14714
|
-
0x00, 0x01,
|
14715
|
-
// data_reference_index
|
14716
|
-
0x00, 0x00,
|
14717
|
-
// pre_defined
|
14718
|
-
0x00, 0x00,
|
14719
|
-
// reserved
|
14720
|
-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
14721
|
-
// pre_defined
|
14722
|
-
width >> 8 & 0xff, width & 0xff,
|
14723
|
-
// width
|
14724
|
-
height >> 8 & 0xff, height & 0xff,
|
14725
|
-
// height
|
14726
|
-
0x00, 0x48, 0x00, 0x00,
|
14727
|
-
// horizresolution
|
14728
|
-
0x00, 0x48, 0x00, 0x00,
|
14729
|
-
// vertresolution
|
14730
|
-
0x00, 0x00, 0x00, 0x00,
|
14731
|
-
// reserved
|
14732
|
-
0x00, 0x01,
|
14733
|
-
// frame_count
|
14734
|
-
0x12, 0x64, 0x61, 0x69, 0x6c,
|
14735
|
-
// dailymotion/hls.js
|
14736
|
-
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,
|
14737
|
-
// compressorname
|
14738
|
-
0x00, 0x18,
|
14739
|
-
// depth = 24
|
14740
|
-
0x11, 0x11]),
|
14741
|
-
// pre_defined = -1
|
14742
|
-
hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
|
14743
|
-
// bufferSizeDB
|
14744
|
-
0x00, 0x2d, 0xc6, 0xc0,
|
14745
|
-
// maxBitrate
|
14746
|
-
0x00, 0x2d, 0xc6, 0xc0])),
|
14747
|
-
// avgBitrate
|
14748
|
-
MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
|
14749
|
-
// hSpacing
|
14750
|
-
hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
|
14751
|
-
// vSpacing
|
14752
|
-
vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
|
14753
|
-
};
|
14754
13866
|
return MP4;
|
14755
13867
|
}();
|
14756
13868
|
MP4.types = void 0;
|
@@ -15152,9 +14264,9 @@
|
|
15152
14264
|
var foundOverlap = delta < -1;
|
15153
14265
|
if (foundHole || foundOverlap) {
|
15154
14266
|
if (foundHole) {
|
15155
|
-
logger.warn(
|
14267
|
+
logger.warn("AVC: " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
|
15156
14268
|
} else {
|
15157
|
-
logger.warn(
|
14269
|
+
logger.warn("AVC: " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
|
15158
14270
|
}
|
15159
14271
|
if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
|
15160
14272
|
firstDTS = nextAvcDts;
|
@@ -15163,24 +14275,12 @@
|
|
15163
14275
|
inputSamples[0].dts = firstDTS;
|
15164
14276
|
inputSamples[0].pts = firstPTS;
|
15165
14277
|
} else {
|
15166
|
-
var isPTSOrderRetained = true;
|
15167
14278
|
for (var _i = 0; _i < inputSamples.length; _i++) {
|
15168
|
-
if (inputSamples[_i].dts > firstPTS
|
14279
|
+
if (inputSamples[_i].dts > firstPTS) {
|
15169
14280
|
break;
|
15170
14281
|
}
|
15171
|
-
var prevPTS = inputSamples[_i].pts;
|
15172
14282
|
inputSamples[_i].dts -= delta;
|
15173
14283
|
inputSamples[_i].pts -= delta;
|
15174
|
-
|
15175
|
-
// check to see if this sample's PTS order has changed
|
15176
|
-
// relative to the next one
|
15177
|
-
if (_i < inputSamples.length - 1) {
|
15178
|
-
var nextSamplePTS = inputSamples[_i + 1].pts;
|
15179
|
-
var currentSamplePTS = inputSamples[_i].pts;
|
15180
|
-
var currentOrder = nextSamplePTS <= currentSamplePTS;
|
15181
|
-
var prevOrder = nextSamplePTS <= prevPTS;
|
15182
|
-
isPTSOrderRetained = currentOrder == prevOrder;
|
15183
|
-
}
|
15184
14284
|
}
|
15185
14285
|
}
|
15186
14286
|
logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
|
@@ -15328,7 +14428,7 @@
|
|
15328
14428
|
}
|
15329
14429
|
}
|
15330
14430
|
}
|
15331
|
-
// next AVC
|
14431
|
+
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
15332
14432
|
mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
|
15333
14433
|
this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
|
15334
14434
|
this.videoSampleDuration = mp4SampleDuration;
|
@@ -15463,7 +14563,7 @@
|
|
15463
14563
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
15464
14564
|
for (var j = 0; j < missing; j++) {
|
15465
14565
|
var newStamp = Math.max(nextPts, 0);
|
15466
|
-
var fillFrame = AAC.getSilentFrame(track.
|
14566
|
+
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15467
14567
|
if (!fillFrame) {
|
15468
14568
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
15469
14569
|
fillFrame = sample.unit.subarray();
|
@@ -15591,7 +14691,7 @@
|
|
15591
14691
|
// samples count of this segment's duration
|
15592
14692
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
15593
14693
|
// silent frame
|
15594
|
-
var silentFrame = AAC.getSilentFrame(track.
|
14694
|
+
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15595
14695
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
15596
14696
|
// Can't remux if we can't generate a silent frame...
|
15597
14697
|
if (!silentFrame) {
|
@@ -15981,15 +15081,13 @@
|
|
15981
15081
|
duration = transmuxConfig.duration,
|
15982
15082
|
initSegmentData = transmuxConfig.initSegmentData;
|
15983
15083
|
var keyData = getEncryptionType(uintData, decryptdata);
|
15984
|
-
if (keyData &&
|
15084
|
+
if (keyData && keyData.method === 'AES-128') {
|
15985
15085
|
var decrypter = this.getDecrypter();
|
15986
|
-
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
15987
|
-
|
15988
15086
|
// Software decryption is synchronous; webCrypto is not
|
15989
15087
|
if (decrypter.isSync()) {
|
15990
15088
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
15991
15089
|
// data is handled in the flush() call
|
15992
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15090
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
15993
15091
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
15994
15092
|
var loadingParts = chunkMeta.part > -1;
|
15995
15093
|
if (loadingParts) {
|
@@ -16001,7 +15099,7 @@
|
|
16001
15099
|
}
|
16002
15100
|
uintData = new Uint8Array(decryptedData);
|
16003
15101
|
} else {
|
16004
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15102
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
16005
15103
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
16006
15104
|
// the decrypted data has been transmuxed
|
16007
15105
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -16622,7 +15720,7 @@
|
|
16622
15720
|
observer.on(Events.ERROR, forwardMessage);
|
16623
15721
|
|
16624
15722
|
// forward logger events to main thread
|
16625
|
-
var forwardWorkerLogs = function forwardWorkerLogs(
|
15723
|
+
var forwardWorkerLogs = function forwardWorkerLogs() {
|
16626
15724
|
var _loop = function _loop(logFn) {
|
16627
15725
|
var func = function func(message) {
|
16628
15726
|
forwardMessage('workerLog', {
|
@@ -16643,8 +15741,8 @@
|
|
16643
15741
|
{
|
16644
15742
|
var config = JSON.parse(data.config);
|
16645
15743
|
self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
|
16646
|
-
|
16647
|
-
forwardWorkerLogs(
|
15744
|
+
enableLogs(config.debug, data.id);
|
15745
|
+
forwardWorkerLogs();
|
16648
15746
|
forwardMessage('init', null);
|
16649
15747
|
break;
|
16650
15748
|
}
|
@@ -16818,7 +15916,16 @@
|
|
16818
15916
|
this.observer = new EventEmitter();
|
16819
15917
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
16820
15918
|
this.observer.on(Events.ERROR, forwardMessage);
|
16821
|
-
var
|
15919
|
+
var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
|
15920
|
+
isTypeSupported: function isTypeSupported() {
|
15921
|
+
return false;
|
15922
|
+
}
|
15923
|
+
};
|
15924
|
+
var m2tsTypeSupported = {
|
15925
|
+
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
15926
|
+
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
15927
|
+
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
15928
|
+
};
|
16822
15929
|
|
16823
15930
|
// navigator.vendor is not always available in Web Worker
|
16824
15931
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -17102,7 +16209,7 @@
|
|
17102
16209
|
_inheritsLoose(AudioStreamController, _BaseStreamController);
|
17103
16210
|
function AudioStreamController(hls, fragmentTracker, keyLoader) {
|
17104
16211
|
var _this;
|
17105
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
|
16212
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]', PlaylistLevelType.AUDIO) || this;
|
17106
16213
|
_this.videoBuffer = null;
|
17107
16214
|
_this.videoTrackCC = -1;
|
17108
16215
|
_this.waitingVideoCC = -1;
|
@@ -17114,24 +16221,27 @@
|
|
17114
16221
|
_this.flushing = false;
|
17115
16222
|
_this.bufferFlushed = false;
|
17116
16223
|
_this.cachedTrackLoadedData = null;
|
17117
|
-
_this.
|
16224
|
+
_this._registerListeners();
|
17118
16225
|
return _this;
|
17119
16226
|
}
|
17120
16227
|
var _proto = AudioStreamController.prototype;
|
17121
16228
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
17122
|
-
this.
|
16229
|
+
this._unregisterListeners();
|
17123
16230
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
17124
16231
|
this.mainDetails = null;
|
17125
16232
|
this.bufferedTrack = null;
|
17126
16233
|
this.switchingTrack = null;
|
17127
16234
|
};
|
17128
|
-
_proto.
|
17129
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
16235
|
+
_proto._registerListeners = function _registerListeners() {
|
17130
16236
|
var hls = this.hls;
|
16237
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16238
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16239
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17131
16240
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17132
16241
|
hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
17133
16242
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
17134
16243
|
hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16244
|
+
hls.on(Events.ERROR, this.onError, this);
|
17135
16245
|
hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
|
17136
16246
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
17137
16247
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -17139,16 +16249,16 @@
|
|
17139
16249
|
hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
|
17140
16250
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
17141
16251
|
};
|
17142
|
-
_proto.
|
16252
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
17143
16253
|
var hls = this.hls;
|
17144
|
-
|
17145
|
-
|
17146
|
-
|
17147
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
16254
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16255
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16256
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17148
16257
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17149
16258
|
hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
17150
16259
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
17151
16260
|
hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16261
|
+
hls.off(Events.ERROR, this.onError, this);
|
17152
16262
|
hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
|
17153
16263
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
17154
16264
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -17307,13 +16417,12 @@
|
|
17307
16417
|
trackId = this.trackId;
|
17308
16418
|
var config = hls.config;
|
17309
16419
|
|
17310
|
-
// 1. if
|
17311
|
-
// 2. if video not attached AND
|
16420
|
+
// 1. if video not attached AND
|
17312
16421
|
// start fragment already requested OR start frag prefetch not enabled
|
17313
|
-
//
|
16422
|
+
// 2. if tracks or track not loaded and selected
|
17314
16423
|
// then exit loop
|
17315
16424
|
// => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
|
17316
|
-
if (!
|
16425
|
+
if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
17317
16426
|
return;
|
17318
16427
|
}
|
17319
16428
|
var levelInfo = levels[trackId];
|
@@ -17842,7 +16951,7 @@
|
|
17842
16951
|
_inheritsLoose(AudioTrackController, _BasePlaylistControll);
|
17843
16952
|
function AudioTrackController(hls) {
|
17844
16953
|
var _this;
|
17845
|
-
_this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
|
16954
|
+
_this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this;
|
17846
16955
|
_this.tracks = [];
|
17847
16956
|
_this.groupIds = null;
|
17848
16957
|
_this.tracksInGroup = [];
|
@@ -18171,23 +17280,26 @@
|
|
18171
17280
|
_inheritsLoose(SubtitleStreamController, _BaseStreamController);
|
18172
17281
|
function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
|
18173
17282
|
var _this;
|
18174
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
|
17283
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]', PlaylistLevelType.SUBTITLE) || this;
|
18175
17284
|
_this.currentTrackId = -1;
|
18176
17285
|
_this.tracksBuffered = [];
|
18177
17286
|
_this.mainDetails = null;
|
18178
|
-
_this.
|
17287
|
+
_this._registerListeners();
|
18179
17288
|
return _this;
|
18180
17289
|
}
|
18181
17290
|
var _proto = SubtitleStreamController.prototype;
|
18182
17291
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
18183
|
-
this.
|
17292
|
+
this._unregisterListeners();
|
18184
17293
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
18185
17294
|
this.mainDetails = null;
|
18186
17295
|
};
|
18187
|
-
_proto.
|
18188
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
17296
|
+
_proto._registerListeners = function _registerListeners() {
|
18189
17297
|
var hls = this.hls;
|
17298
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17299
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17300
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
18190
17301
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17302
|
+
hls.on(Events.ERROR, this.onError, this);
|
18191
17303
|
hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
18192
17304
|
hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
18193
17305
|
hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -18195,10 +17307,13 @@
|
|
18195
17307
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
18196
17308
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
18197
17309
|
};
|
18198
|
-
_proto.
|
18199
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
17310
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
18200
17311
|
var hls = this.hls;
|
17312
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17313
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17314
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
18201
17315
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17316
|
+
hls.off(Events.ERROR, this.onError, this);
|
18202
17317
|
hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
18203
17318
|
hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
18204
17319
|
hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -18421,10 +17536,10 @@
|
|
18421
17536
|
return;
|
18422
17537
|
}
|
18423
17538
|
// check to see if the payload needs to be decrypted
|
18424
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
17539
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
18425
17540
|
var startTime = performance.now();
|
18426
17541
|
// decrypt the subtitles
|
18427
|
-
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
17542
|
+
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
18428
17543
|
hls.trigger(Events.ERROR, {
|
18429
17544
|
type: ErrorTypes.MEDIA_ERROR,
|
18430
17545
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -18556,7 +17671,7 @@
|
|
18556
17671
|
_inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
|
18557
17672
|
function SubtitleTrackController(hls) {
|
18558
17673
|
var _this;
|
18559
|
-
_this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
|
17674
|
+
_this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this;
|
18560
17675
|
_this.media = null;
|
18561
17676
|
_this.tracks = [];
|
18562
17677
|
_this.groupIds = null;
|
@@ -18565,12 +17680,12 @@
|
|
18565
17680
|
_this.currentTrack = null;
|
18566
17681
|
_this.selectDefaultTrack = true;
|
18567
17682
|
_this.queuedDefaultTrack = -1;
|
18568
|
-
_this.useTextTrackPolling = false;
|
18569
|
-
_this.subtitlePollingInterval = -1;
|
18570
|
-
_this._subtitleDisplay = true;
|
18571
17683
|
_this.asyncPollTrackChange = function () {
|
18572
17684
|
return _this.pollTrackChange(0);
|
18573
17685
|
};
|
17686
|
+
_this.useTextTrackPolling = false;
|
17687
|
+
_this.subtitlePollingInterval = -1;
|
17688
|
+
_this._subtitleDisplay = true;
|
18574
17689
|
_this.onTextTracksChanged = function () {
|
18575
17690
|
if (!_this.useTextTrackPolling) {
|
18576
17691
|
self.clearInterval(_this.subtitlePollingInterval);
|
@@ -18606,7 +17721,6 @@
|
|
18606
17721
|
this.tracks.length = 0;
|
18607
17722
|
this.tracksInGroup.length = 0;
|
18608
17723
|
this.currentTrack = null;
|
18609
|
-
// @ts-ignore
|
18610
17724
|
this.onTextTracksChanged = this.asyncPollTrackChange = null;
|
18611
17725
|
_BasePlaylistControll.prototype.destroy.call(this);
|
18612
17726
|
};
|
@@ -19080,57 +18194,57 @@
|
|
19080
18194
|
}();
|
19081
18195
|
|
19082
18196
|
var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
|
19083
|
-
var BufferController = /*#__PURE__*/function (
|
19084
|
-
_inheritsLoose(BufferController, _Logger);
|
18197
|
+
var BufferController = /*#__PURE__*/function () {
|
19085
18198
|
function BufferController(hls) {
|
19086
|
-
var _this;
|
19087
|
-
_this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
|
18199
|
+
var _this = this;
|
19088
18200
|
// The level details used to determine duration, target-duration and live
|
19089
|
-
|
18201
|
+
this.details = null;
|
19090
18202
|
// cache the self generated object url to detect hijack of video tag
|
19091
|
-
|
18203
|
+
this._objectUrl = null;
|
19092
18204
|
// A queue of buffer operations which require the SourceBuffer to not be updating upon execution
|
19093
|
-
|
18205
|
+
this.operationQueue = void 0;
|
19094
18206
|
// References to event listeners for each SourceBuffer, so that they can be referenced for event removal
|
19095
|
-
|
19096
|
-
|
18207
|
+
this.listeners = void 0;
|
18208
|
+
this.hls = void 0;
|
19097
18209
|
// The number of BUFFER_CODEC events received before any sourceBuffers are created
|
19098
|
-
|
18210
|
+
this.bufferCodecEventsExpected = 0;
|
19099
18211
|
// The total number of BUFFER_CODEC events received
|
19100
|
-
|
18212
|
+
this._bufferCodecEventsTotal = 0;
|
19101
18213
|
// A reference to the attached media element
|
19102
|
-
|
18214
|
+
this.media = null;
|
19103
18215
|
// A reference to the active media source
|
19104
|
-
|
18216
|
+
this.mediaSource = null;
|
19105
18217
|
// Last MP3 audio chunk appended
|
19106
|
-
|
19107
|
-
|
18218
|
+
this.lastMpegAudioChunk = null;
|
18219
|
+
this.appendSource = void 0;
|
19108
18220
|
// counters
|
19109
|
-
|
18221
|
+
this.appendErrors = {
|
19110
18222
|
audio: 0,
|
19111
18223
|
video: 0,
|
19112
18224
|
audiovideo: 0
|
19113
18225
|
};
|
19114
|
-
|
19115
|
-
|
19116
|
-
|
19117
|
-
|
18226
|
+
this.tracks = {};
|
18227
|
+
this.pendingTracks = {};
|
18228
|
+
this.sourceBuffer = void 0;
|
18229
|
+
this.log = void 0;
|
18230
|
+
this.warn = void 0;
|
18231
|
+
this.error = void 0;
|
18232
|
+
this._onEndStreaming = function (event) {
|
19118
18233
|
if (!_this.hls) {
|
19119
18234
|
return;
|
19120
18235
|
}
|
19121
18236
|
_this.hls.pauseBuffering();
|
19122
18237
|
};
|
19123
|
-
|
18238
|
+
this._onStartStreaming = function (event) {
|
19124
18239
|
if (!_this.hls) {
|
19125
18240
|
return;
|
19126
18241
|
}
|
19127
18242
|
_this.hls.resumeBuffering();
|
19128
18243
|
};
|
19129
18244
|
// Keep as arrow functions so that we can directly reference these functions directly as event listeners
|
19130
|
-
|
19131
|
-
var
|
19132
|
-
|
19133
|
-
mediaSource = _assertThisInitialize.mediaSource;
|
18245
|
+
this._onMediaSourceOpen = function () {
|
18246
|
+
var media = _this.media,
|
18247
|
+
mediaSource = _this.mediaSource;
|
19134
18248
|
_this.log('Media source opened');
|
19135
18249
|
if (media) {
|
19136
18250
|
media.removeEventListener('emptied', _this._onMediaEmptied);
|
@@ -19146,25 +18260,27 @@
|
|
19146
18260
|
}
|
19147
18261
|
_this.checkPendingTracks();
|
19148
18262
|
};
|
19149
|
-
|
18263
|
+
this._onMediaSourceClose = function () {
|
19150
18264
|
_this.log('Media source closed');
|
19151
18265
|
};
|
19152
|
-
|
18266
|
+
this._onMediaSourceEnded = function () {
|
19153
18267
|
_this.log('Media source ended');
|
19154
18268
|
};
|
19155
|
-
|
19156
|
-
var
|
19157
|
-
|
19158
|
-
_objectUrl = _assertThisInitialize2._objectUrl;
|
18269
|
+
this._onMediaEmptied = function () {
|
18270
|
+
var mediaSrc = _this.mediaSrc,
|
18271
|
+
_objectUrl = _this._objectUrl;
|
19159
18272
|
if (mediaSrc !== _objectUrl) {
|
19160
|
-
|
18273
|
+
logger.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
|
19161
18274
|
}
|
19162
18275
|
};
|
19163
|
-
|
19164
|
-
|
19165
|
-
|
19166
|
-
|
19167
|
-
|
18276
|
+
this.hls = hls;
|
18277
|
+
var logPrefix = '[buffer-controller]';
|
18278
|
+
this.appendSource = hls.config.preferManagedMediaSource;
|
18279
|
+
this.log = logger.log.bind(logger, logPrefix);
|
18280
|
+
this.warn = logger.warn.bind(logger, logPrefix);
|
18281
|
+
this.error = logger.error.bind(logger, logPrefix);
|
18282
|
+
this._initSourceBuffer();
|
18283
|
+
this.registerListeners();
|
19168
18284
|
}
|
19169
18285
|
var _proto = BufferController.prototype;
|
19170
18286
|
_proto.hasSourceTypes = function hasSourceTypes() {
|
@@ -19176,12 +18292,6 @@
|
|
19176
18292
|
this.lastMpegAudioChunk = null;
|
19177
18293
|
// @ts-ignore
|
19178
18294
|
this.hls = null;
|
19179
|
-
// @ts-ignore
|
19180
|
-
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
19181
|
-
// @ts-ignore
|
19182
|
-
this._onMediaSourceEnded = null;
|
19183
|
-
// @ts-ignore
|
19184
|
-
this._onStartStreaming = this._onEndStreaming = null;
|
19185
18295
|
};
|
19186
18296
|
_proto.registerListeners = function registerListeners() {
|
19187
18297
|
var hls = this.hls;
|
@@ -19339,7 +18449,6 @@
|
|
19339
18449
|
_this2.resetBuffer(type);
|
19340
18450
|
});
|
19341
18451
|
this._initSourceBuffer();
|
19342
|
-
this.hls.resumeBuffering();
|
19343
18452
|
};
|
19344
18453
|
_proto.resetBuffer = function resetBuffer(type) {
|
19345
18454
|
var sb = this.sourceBuffer[type];
|
@@ -20043,7 +19152,7 @@
|
|
20043
19152
|
}
|
20044
19153
|
}]);
|
20045
19154
|
return BufferController;
|
20046
|
-
}(
|
19155
|
+
}();
|
20047
19156
|
function removeSourceChildren(node) {
|
20048
19157
|
var sourceChildren = node.querySelectorAll('source');
|
20049
19158
|
[].slice.call(sourceChildren).forEach(function (source) {
|
@@ -22482,12 +21591,14 @@
|
|
22482
21591
|
this.cea608Parser1 = this.cea608Parser2 = undefined;
|
22483
21592
|
};
|
22484
21593
|
_proto.initCea608Parsers = function initCea608Parsers() {
|
22485
|
-
|
22486
|
-
|
22487
|
-
|
22488
|
-
|
22489
|
-
|
22490
|
-
|
21594
|
+
if (this.config.enableCEA708Captions && (!this.cea608Parser1 || !this.cea608Parser2)) {
|
21595
|
+
var channel1 = new OutputFilter(this, 'textTrack1');
|
21596
|
+
var channel2 = new OutputFilter(this, 'textTrack2');
|
21597
|
+
var channel3 = new OutputFilter(this, 'textTrack3');
|
21598
|
+
var channel4 = new OutputFilter(this, 'textTrack4');
|
21599
|
+
this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
|
21600
|
+
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21601
|
+
}
|
22491
21602
|
};
|
22492
21603
|
_proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
|
22493
21604
|
// skip cues which overlap more than 50% with previously parsed time ranges
|
@@ -22722,7 +21833,7 @@
|
|
22722
21833
|
return t.label;
|
22723
21834
|
});
|
22724
21835
|
if (unusedTextTracks.length) {
|
22725
|
-
|
21836
|
+
logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
|
22726
21837
|
}
|
22727
21838
|
}
|
22728
21839
|
} else if (this.tracks.length) {
|
@@ -22768,20 +21879,23 @@
|
|
22768
21879
|
return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
|
22769
21880
|
};
|
22770
21881
|
_proto.onFragLoading = function onFragLoading(event, data) {
|
21882
|
+
this.initCea608Parsers();
|
21883
|
+
var cea608Parser1 = this.cea608Parser1,
|
21884
|
+
cea608Parser2 = this.cea608Parser2,
|
21885
|
+
lastCc = this.lastCc,
|
21886
|
+
lastSn = this.lastSn,
|
21887
|
+
lastPartIndex = this.lastPartIndex;
|
21888
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
21889
|
+
return;
|
21890
|
+
}
|
22771
21891
|
// if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
|
22772
|
-
if (
|
21892
|
+
if (data.frag.type === PlaylistLevelType.MAIN) {
|
22773
21893
|
var _data$part$index, _data$part;
|
22774
|
-
var cea608Parser1 = this.cea608Parser1,
|
22775
|
-
cea608Parser2 = this.cea608Parser2,
|
22776
|
-
lastSn = this.lastSn;
|
22777
|
-
if (!cea608Parser1 || !cea608Parser2) {
|
22778
|
-
return;
|
22779
|
-
}
|
22780
21894
|
var _data$frag = data.frag,
|
22781
21895
|
cc = _data$frag.cc,
|
22782
21896
|
sn = _data$frag.sn;
|
22783
|
-
var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
22784
|
-
if (!(sn === lastSn + 1 || sn === lastSn && partIndex ===
|
21897
|
+
var partIndex = (_data$part$index = data == null ? void 0 : (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
21898
|
+
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
|
22785
21899
|
cea608Parser1.reset();
|
22786
21900
|
cea608Parser2.reset();
|
22787
21901
|
}
|
@@ -22837,7 +21951,7 @@
|
|
22837
21951
|
frag: frag
|
22838
21952
|
});
|
22839
21953
|
}, function (error) {
|
22840
|
-
|
21954
|
+
logger.log("Failed to parse IMSC1: " + error);
|
22841
21955
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
22842
21956
|
success: false,
|
22843
21957
|
frag: frag,
|
@@ -22875,7 +21989,7 @@
|
|
22875
21989
|
_this5._fallbackToIMSC1(frag, payload);
|
22876
21990
|
}
|
22877
21991
|
// Something went wrong while parsing. Trigger event with success false.
|
22878
|
-
|
21992
|
+
logger.log("Failed to parse VTT cue: " + error);
|
22879
21993
|
if (missingInitPTS && maxAvCC > frag.cc) {
|
22880
21994
|
return;
|
22881
21995
|
}
|
@@ -22937,7 +22051,10 @@
|
|
22937
22051
|
this.captionsTracks = {};
|
22938
22052
|
};
|
22939
22053
|
_proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
|
22940
|
-
|
22054
|
+
this.initCea608Parsers();
|
22055
|
+
var cea608Parser1 = this.cea608Parser1,
|
22056
|
+
cea608Parser2 = this.cea608Parser2;
|
22057
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
22941
22058
|
return;
|
22942
22059
|
}
|
22943
22060
|
var frag = data.frag,
|
@@ -22950,12 +22067,9 @@
|
|
22950
22067
|
for (var i = 0; i < samples.length; i++) {
|
22951
22068
|
var ccBytes = samples[i].bytes;
|
22952
22069
|
if (ccBytes) {
|
22953
|
-
if (!this.cea608Parser1) {
|
22954
|
-
this.initCea608Parsers();
|
22955
|
-
}
|
22956
22070
|
var ccdatas = this.extractCea608Data(ccBytes);
|
22957
|
-
|
22958
|
-
|
22071
|
+
cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22072
|
+
cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22959
22073
|
}
|
22960
22074
|
}
|
22961
22075
|
};
|
@@ -23147,7 +22261,7 @@
|
|
23147
22261
|
var hls = this.hls;
|
23148
22262
|
var maxLevel = this.getMaxLevel(levels.length - 1);
|
23149
22263
|
if (maxLevel !== this.autoLevelCapping) {
|
23150
|
-
|
22264
|
+
logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
23151
22265
|
}
|
23152
22266
|
hls.autoLevelCapping = maxLevel;
|
23153
22267
|
if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
|
@@ -23337,10 +22451,10 @@
|
|
23337
22451
|
totalDroppedFrames: droppedFrames
|
23338
22452
|
});
|
23339
22453
|
if (droppedFPS > 0) {
|
23340
|
-
//
|
22454
|
+
// logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
23341
22455
|
if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
|
23342
22456
|
var currentLevel = hls.currentLevel;
|
23343
|
-
|
22457
|
+
logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
23344
22458
|
if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
|
23345
22459
|
currentLevel = currentLevel - 1;
|
23346
22460
|
hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
|
@@ -23373,6 +22487,7 @@
|
|
23373
22487
|
return FPSController;
|
23374
22488
|
}();
|
23375
22489
|
|
22490
|
+
var LOGGER_PREFIX = '[eme]';
|
23376
22491
|
/**
|
23377
22492
|
* Controller to deal with encrypted media extensions (EME)
|
23378
22493
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
|
@@ -23380,122 +22495,26 @@
|
|
23380
22495
|
* @class
|
23381
22496
|
* @constructor
|
23382
22497
|
*/
|
23383
|
-
var EMEController = /*#__PURE__*/function (
|
23384
|
-
_inheritsLoose(EMEController, _Logger);
|
22498
|
+
var EMEController = /*#__PURE__*/function () {
|
23385
22499
|
function EMEController(hls) {
|
23386
|
-
|
23387
|
-
|
23388
|
-
|
23389
|
-
|
23390
|
-
|
23391
|
-
|
23392
|
-
|
23393
|
-
|
23394
|
-
|
23395
|
-
|
23396
|
-
|
23397
|
-
|
23398
|
-
|
23399
|
-
|
23400
|
-
|
23401
|
-
|
23402
|
-
|
23403
|
-
|
23404
|
-
return;
|
23405
|
-
}
|
23406
|
-
var keyId;
|
23407
|
-
var keySystemDomain;
|
23408
|
-
if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
23409
|
-
// Match sinf keyId to playlist skd://keyId=
|
23410
|
-
var json = bin2str(new Uint8Array(initData));
|
23411
|
-
try {
|
23412
|
-
var sinf = base64Decode(JSON.parse(json).sinf);
|
23413
|
-
var tenc = parseSinf(new Uint8Array(sinf));
|
23414
|
-
if (!tenc) {
|
23415
|
-
return;
|
23416
|
-
}
|
23417
|
-
keyId = tenc.subarray(8, 24);
|
23418
|
-
keySystemDomain = KeySystems.FAIRPLAY;
|
23419
|
-
} catch (error) {
|
23420
|
-
_this.warn('Failed to parse sinf "encrypted" event message initData');
|
23421
|
-
return;
|
23422
|
-
}
|
23423
|
-
} else {
|
23424
|
-
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
23425
|
-
var psshInfo = parsePssh(initData);
|
23426
|
-
if (psshInfo === null) {
|
23427
|
-
return;
|
23428
|
-
}
|
23429
|
-
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
23430
|
-
keyId = psshInfo.data.subarray(8, 24);
|
23431
|
-
}
|
23432
|
-
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
23433
|
-
}
|
23434
|
-
if (!keySystemDomain || !keyId) {
|
23435
|
-
return;
|
23436
|
-
}
|
23437
|
-
var keyIdHex = Hex.hexDump(keyId);
|
23438
|
-
var _assertThisInitialize = _assertThisInitialized(_this),
|
23439
|
-
keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
|
23440
|
-
mediaKeySessions = _assertThisInitialize.mediaKeySessions;
|
23441
|
-
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
23442
|
-
var _loop = function _loop() {
|
23443
|
-
// Match playlist key
|
23444
|
-
var keyContext = mediaKeySessions[i];
|
23445
|
-
var decryptdata = keyContext.decryptdata;
|
23446
|
-
if (decryptdata.pssh || !decryptdata.keyId) {
|
23447
|
-
return 0; // continue
|
23448
|
-
}
|
23449
|
-
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
23450
|
-
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
23451
|
-
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
23452
|
-
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
23453
|
-
decryptdata.pssh = new Uint8Array(initData);
|
23454
|
-
decryptdata.keyId = keyId;
|
23455
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
23456
|
-
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
23457
|
-
});
|
23458
|
-
return 1; // break
|
23459
|
-
}
|
23460
|
-
},
|
23461
|
-
_ret;
|
23462
|
-
for (var i = 0; i < mediaKeySessions.length; i++) {
|
23463
|
-
_ret = _loop();
|
23464
|
-
if (_ret === 0) continue;
|
23465
|
-
if (_ret === 1) break;
|
23466
|
-
}
|
23467
|
-
if (!keySessionContextPromise) {
|
23468
|
-
// Clear-lead key (not encountered in playlist)
|
23469
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
23470
|
-
var _keySystemToKeySystem;
|
23471
|
-
var keySystem = _ref.keySystem,
|
23472
|
-
mediaKeys = _ref.mediaKeys;
|
23473
|
-
_this.throwIfDestroyed();
|
23474
|
-
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
23475
|
-
decryptdata.pssh = new Uint8Array(initData);
|
23476
|
-
decryptdata.keyId = keyId;
|
23477
|
-
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23478
|
-
_this.throwIfDestroyed();
|
23479
|
-
var keySessionContext = _this.createMediaKeySessionContext({
|
23480
|
-
decryptdata: decryptdata,
|
23481
|
-
keySystem: keySystem,
|
23482
|
-
mediaKeys: mediaKeys
|
23483
|
-
});
|
23484
|
-
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
23485
|
-
});
|
23486
|
-
});
|
23487
|
-
}
|
23488
|
-
keySessionContextPromise.catch(function (error) {
|
23489
|
-
return _this.handleError(error);
|
23490
|
-
});
|
23491
|
-
};
|
23492
|
-
_this.onWaitingForKey = function (event) {
|
23493
|
-
_this.log("\"" + event.type + "\" event");
|
23494
|
-
};
|
23495
|
-
_this.hls = hls;
|
23496
|
-
_this.config = hls.config;
|
23497
|
-
_this.registerListeners();
|
23498
|
-
return _this;
|
22500
|
+
this.hls = void 0;
|
22501
|
+
this.config = void 0;
|
22502
|
+
this.media = null;
|
22503
|
+
this.keyFormatPromise = null;
|
22504
|
+
this.keySystemAccessPromises = {};
|
22505
|
+
this._requestLicenseFailureCount = 0;
|
22506
|
+
this.mediaKeySessions = [];
|
22507
|
+
this.keyIdToKeySessionPromise = {};
|
22508
|
+
this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
22509
|
+
this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
|
22510
|
+
this.onWaitingForKey = this._onWaitingForKey.bind(this);
|
22511
|
+
this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
|
22512
|
+
this.log = logger.log.bind(logger, LOGGER_PREFIX);
|
22513
|
+
this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
|
22514
|
+
this.error = logger.error.bind(logger, LOGGER_PREFIX);
|
22515
|
+
this.hls = hls;
|
22516
|
+
this.config = hls.config;
|
22517
|
+
this.registerListeners();
|
23499
22518
|
}
|
23500
22519
|
var _proto = EMEController.prototype;
|
23501
22520
|
_proto.destroy = function destroy() {
|
@@ -23507,9 +22526,9 @@
|
|
23507
22526
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
23508
22527
|
config.drmSystems = config.drmSystemOptions = {};
|
23509
22528
|
// @ts-ignore
|
23510
|
-
this.hls = this.
|
22529
|
+
this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
|
23511
22530
|
// @ts-ignore
|
23512
|
-
this.
|
22531
|
+
this.config = null;
|
23513
22532
|
};
|
23514
22533
|
_proto.registerListeners = function registerListeners() {
|
23515
22534
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -23548,7 +22567,7 @@
|
|
23548
22567
|
}
|
23549
22568
|
};
|
23550
22569
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
23551
|
-
var
|
22570
|
+
var _this = this;
|
23552
22571
|
var levels = this.hls.levels;
|
23553
22572
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
23554
22573
|
return !!value && a.indexOf(value) === i;
|
@@ -23565,7 +22584,7 @@
|
|
23565
22584
|
return new Promise(function (resolve, reject) {
|
23566
22585
|
var attempt = function attempt(keySystems) {
|
23567
22586
|
var keySystem = keySystems.shift();
|
23568
|
-
|
22587
|
+
_this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
23569
22588
|
return resolve({
|
23570
22589
|
keySystem: keySystem,
|
23571
22590
|
mediaKeys: mediaKeys
|
@@ -23600,7 +22619,7 @@
|
|
23600
22619
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
23601
22620
|
};
|
23602
22621
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
23603
|
-
var
|
22622
|
+
var _this2 = this;
|
23604
22623
|
// This can throw, but is caught in event handler callpath
|
23605
22624
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
23606
22625
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -23612,23 +22631,23 @@
|
|
23612
22631
|
keySystemAccess: keySystemAccess
|
23613
22632
|
};
|
23614
22633
|
keySystemAccess.catch(function (error) {
|
23615
|
-
|
22634
|
+
_this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
23616
22635
|
});
|
23617
22636
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
23618
|
-
|
23619
|
-
var certificateRequest =
|
23620
|
-
|
22637
|
+
_this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
22638
|
+
var certificateRequest = _this2.fetchServerCertificate(keySystem);
|
22639
|
+
_this2.log("Create media-keys for \"" + keySystem + "\"");
|
23621
22640
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
23622
|
-
|
22641
|
+
_this2.log("Media-keys created for \"" + keySystem + "\"");
|
23623
22642
|
return certificateRequest.then(function (certificate) {
|
23624
22643
|
if (certificate) {
|
23625
|
-
return
|
22644
|
+
return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
23626
22645
|
}
|
23627
22646
|
return mediaKeys;
|
23628
22647
|
});
|
23629
22648
|
});
|
23630
22649
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
23631
|
-
|
22650
|
+
_this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
23632
22651
|
});
|
23633
22652
|
return _keySystemAccessPromises.mediaKeys;
|
23634
22653
|
});
|
@@ -23637,10 +22656,10 @@
|
|
23637
22656
|
return keySystemAccessPromises.mediaKeys;
|
23638
22657
|
});
|
23639
22658
|
};
|
23640
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
23641
|
-
var decryptdata =
|
23642
|
-
keySystem =
|
23643
|
-
mediaKeys =
|
22659
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
|
22660
|
+
var decryptdata = _ref.decryptdata,
|
22661
|
+
keySystem = _ref.keySystem,
|
22662
|
+
mediaKeys = _ref.mediaKeys;
|
23644
22663
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
23645
22664
|
var mediaKeysSession = mediaKeys.createSession();
|
23646
22665
|
var mediaKeySessionContext = {
|
@@ -23689,14 +22708,14 @@
|
|
23689
22708
|
return this.keyFormatPromise;
|
23690
22709
|
};
|
23691
22710
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
23692
|
-
var
|
22711
|
+
var _this3 = this;
|
23693
22712
|
return new Promise(function (resolve, reject) {
|
23694
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
22713
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
|
23695
22714
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
23696
22715
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
23697
22716
|
});
|
23698
|
-
return
|
23699
|
-
var keySystem =
|
22717
|
+
return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
|
22718
|
+
var keySystem = _ref2.keySystem;
|
23700
22719
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
23701
22720
|
if (keySystemFormat) {
|
23702
22721
|
resolve(keySystemFormat);
|
@@ -23707,31 +22726,31 @@
|
|
23707
22726
|
});
|
23708
22727
|
};
|
23709
22728
|
_proto.loadKey = function loadKey(data) {
|
23710
|
-
var
|
22729
|
+
var _this4 = this;
|
23711
22730
|
var decryptdata = data.keyInfo.decryptdata;
|
23712
22731
|
var keyId = this.getKeyIdString(decryptdata);
|
23713
22732
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
23714
22733
|
this.log("Starting session for key " + keyDetails);
|
23715
22734
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
23716
22735
|
if (!keySessionContextPromise) {
|
23717
|
-
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (
|
23718
|
-
var keySystem =
|
23719
|
-
mediaKeys =
|
23720
|
-
|
23721
|
-
|
23722
|
-
return
|
23723
|
-
|
23724
|
-
var keySessionContext =
|
22736
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) {
|
22737
|
+
var keySystem = _ref3.keySystem,
|
22738
|
+
mediaKeys = _ref3.mediaKeys;
|
22739
|
+
_this4.throwIfDestroyed();
|
22740
|
+
_this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
22741
|
+
return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22742
|
+
_this4.throwIfDestroyed();
|
22743
|
+
var keySessionContext = _this4.createMediaKeySessionContext({
|
23725
22744
|
keySystem: keySystem,
|
23726
22745
|
mediaKeys: mediaKeys,
|
23727
22746
|
decryptdata: decryptdata
|
23728
22747
|
});
|
23729
22748
|
var scheme = 'cenc';
|
23730
|
-
return
|
22749
|
+
return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
23731
22750
|
});
|
23732
22751
|
});
|
23733
22752
|
keySessionContextPromise.catch(function (error) {
|
23734
|
-
return
|
22753
|
+
return _this4.handleError(error);
|
23735
22754
|
});
|
23736
22755
|
}
|
23737
22756
|
return keySessionContextPromise;
|
@@ -23765,22 +22784,120 @@
|
|
23765
22784
|
var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
|
23766
22785
|
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
23767
22786
|
}
|
23768
|
-
return mediaKeySessionContext;
|
22787
|
+
return mediaKeySessionContext;
|
22788
|
+
};
|
22789
|
+
_proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
|
22790
|
+
if (!keySystemsToAttempt.length) {
|
22791
|
+
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
22792
|
+
}
|
22793
|
+
if (keySystemsToAttempt.length === 0) {
|
22794
|
+
throw new EMEKeyError({
|
22795
|
+
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
22796
|
+
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
22797
|
+
fatal: true
|
22798
|
+
}, "Missing key-system license configuration options " + JSON.stringify({
|
22799
|
+
drmSystems: this.config.drmSystems
|
22800
|
+
}));
|
22801
|
+
}
|
22802
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22803
|
+
};
|
22804
|
+
_proto._onMediaEncrypted = function _onMediaEncrypted(event) {
|
22805
|
+
var _this5 = this;
|
22806
|
+
var initDataType = event.initDataType,
|
22807
|
+
initData = event.initData;
|
22808
|
+
this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
22809
|
+
|
22810
|
+
// Ignore event when initData is null
|
22811
|
+
if (initData === null) {
|
22812
|
+
return;
|
22813
|
+
}
|
22814
|
+
var keyId;
|
22815
|
+
var keySystemDomain;
|
22816
|
+
if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22817
|
+
// Match sinf keyId to playlist skd://keyId=
|
22818
|
+
var json = bin2str(new Uint8Array(initData));
|
22819
|
+
try {
|
22820
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
22821
|
+
var tenc = parseSinf(new Uint8Array(sinf));
|
22822
|
+
if (!tenc) {
|
22823
|
+
return;
|
22824
|
+
}
|
22825
|
+
keyId = tenc.subarray(8, 24);
|
22826
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
22827
|
+
} catch (error) {
|
22828
|
+
this.warn('Failed to parse sinf "encrypted" event message initData');
|
22829
|
+
return;
|
22830
|
+
}
|
22831
|
+
} else {
|
22832
|
+
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22833
|
+
var psshInfo = parsePssh(initData);
|
22834
|
+
if (psshInfo === null) {
|
22835
|
+
return;
|
22836
|
+
}
|
22837
|
+
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22838
|
+
keyId = psshInfo.data.subarray(8, 24);
|
22839
|
+
}
|
22840
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22841
|
+
}
|
22842
|
+
if (!keySystemDomain || !keyId) {
|
22843
|
+
return;
|
22844
|
+
}
|
22845
|
+
var keyIdHex = Hex.hexDump(keyId);
|
22846
|
+
var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
|
22847
|
+
mediaKeySessions = this.mediaKeySessions;
|
22848
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22849
|
+
var _loop = function _loop() {
|
22850
|
+
// Match playlist key
|
22851
|
+
var keyContext = mediaKeySessions[i];
|
22852
|
+
var decryptdata = keyContext.decryptdata;
|
22853
|
+
if (decryptdata.pssh || !decryptdata.keyId) {
|
22854
|
+
return 0; // continue
|
22855
|
+
}
|
22856
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22857
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22858
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22859
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22860
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22861
|
+
decryptdata.keyId = keyId;
|
22862
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22863
|
+
return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22864
|
+
});
|
22865
|
+
return 1; // break
|
22866
|
+
}
|
22867
|
+
},
|
22868
|
+
_ret;
|
22869
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22870
|
+
_ret = _loop();
|
22871
|
+
if (_ret === 0) continue;
|
22872
|
+
if (_ret === 1) break;
|
22873
|
+
}
|
22874
|
+
if (!keySessionContextPromise) {
|
22875
|
+
// Clear-lead key (not encountered in playlist)
|
22876
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
|
22877
|
+
var _keySystemToKeySystem;
|
22878
|
+
var keySystem = _ref4.keySystem,
|
22879
|
+
mediaKeys = _ref4.mediaKeys;
|
22880
|
+
_this5.throwIfDestroyed();
|
22881
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22882
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22883
|
+
decryptdata.keyId = keyId;
|
22884
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22885
|
+
_this5.throwIfDestroyed();
|
22886
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22887
|
+
decryptdata: decryptdata,
|
22888
|
+
keySystem: keySystem,
|
22889
|
+
mediaKeys: mediaKeys
|
22890
|
+
});
|
22891
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22892
|
+
});
|
22893
|
+
});
|
22894
|
+
}
|
22895
|
+
keySessionContextPromise.catch(function (error) {
|
22896
|
+
return _this5.handleError(error);
|
22897
|
+
});
|
23769
22898
|
};
|
23770
|
-
_proto.
|
23771
|
-
|
23772
|
-
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
23773
|
-
}
|
23774
|
-
if (keySystemsToAttempt.length === 0) {
|
23775
|
-
throw new EMEKeyError({
|
23776
|
-
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
23777
|
-
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
23778
|
-
fatal: true
|
23779
|
-
}, "Missing key-system license configuration options " + JSON.stringify({
|
23780
|
-
drmSystems: this.config.drmSystems
|
23781
|
-
}));
|
23782
|
-
}
|
23783
|
-
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22899
|
+
_proto._onWaitingForKey = function _onWaitingForKey(event) {
|
22900
|
+
this.log("\"" + event.type + "\" event");
|
23784
22901
|
};
|
23785
22902
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
23786
22903
|
var _this6 = this;
|
@@ -24237,7 +23354,7 @@
|
|
24237
23354
|
}
|
24238
23355
|
};
|
24239
23356
|
return EMEController;
|
24240
|
-
}(
|
23357
|
+
}();
|
24241
23358
|
EMEController.CDMCleanupPromise = void 0;
|
24242
23359
|
var EMEKeyError = /*#__PURE__*/function (_Error) {
|
24243
23360
|
_inheritsLoose(EMEKeyError, _Error);
|
@@ -24385,6 +23502,18 @@
|
|
24385
23502
|
this.params = params;
|
24386
23503
|
};
|
24387
23504
|
|
23505
|
+
/**
|
23506
|
+
* A class to represent structured field tokens when `Symbol` is not available.
|
23507
|
+
*
|
23508
|
+
* @group Structured Field
|
23509
|
+
*
|
23510
|
+
* @beta
|
23511
|
+
*/
|
23512
|
+
var SfToken = function SfToken(description) {
|
23513
|
+
this.description = void 0;
|
23514
|
+
this.description = description;
|
23515
|
+
};
|
23516
|
+
|
24388
23517
|
var DICT = 'Dict';
|
24389
23518
|
|
24390
23519
|
function format(value) {
|
@@ -24408,25 +23537,29 @@
|
|
24408
23537
|
});
|
24409
23538
|
}
|
24410
23539
|
|
24411
|
-
|
24412
|
-
|
23540
|
+
var BARE_ITEM = 'Bare Item';
|
23541
|
+
|
23542
|
+
var BOOLEAN = 'Boolean';
|
23543
|
+
|
23544
|
+
var BYTES = 'Byte Sequence';
|
23545
|
+
|
23546
|
+
var DECIMAL = 'Decimal';
|
23547
|
+
|
23548
|
+
var INTEGER = 'Integer';
|
23549
|
+
|
23550
|
+
function isInvalidInt(value) {
|
23551
|
+
return value < -999999999999999 || 999999999999999 < value;
|
24413
23552
|
}
|
24414
23553
|
|
24415
|
-
|
24416
|
-
* A class to represent structured field tokens when `Symbol` is not available.
|
24417
|
-
*
|
24418
|
-
* @group Structured Field
|
24419
|
-
*
|
24420
|
-
* @beta
|
24421
|
-
*/
|
24422
|
-
var SfToken = function SfToken(description) {
|
24423
|
-
this.description = void 0;
|
24424
|
-
this.description = description;
|
24425
|
-
};
|
23554
|
+
var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
|
24426
23555
|
|
24427
|
-
var
|
23556
|
+
var TOKEN = 'Token';
|
24428
23557
|
|
24429
|
-
var
|
23558
|
+
var KEY = 'Key';
|
23559
|
+
|
23560
|
+
function serializeError(src, type, cause) {
|
23561
|
+
return throwError('serialize', src, type, cause);
|
23562
|
+
}
|
24430
23563
|
|
24431
23564
|
// 4.1.9. Serializing a Boolean
|
24432
23565
|
//
|
@@ -24465,8 +23598,6 @@
|
|
24465
23598
|
return btoa(String.fromCharCode.apply(String, binary));
|
24466
23599
|
}
|
24467
23600
|
|
24468
|
-
var BYTES = 'Byte Sequence';
|
24469
|
-
|
24470
23601
|
// 4.1.8. Serializing a Byte Sequence
|
24471
23602
|
//
|
24472
23603
|
// Given a Byte Sequence as input_bytes, return an ASCII string suitable
|
@@ -24498,12 +23629,6 @@
|
|
24498
23629
|
return ":" + base64encode(value) + ":";
|
24499
23630
|
}
|
24500
23631
|
|
24501
|
-
var INTEGER = 'Integer';
|
24502
|
-
|
24503
|
-
function isInvalidInt(value) {
|
24504
|
-
return value < -999999999999999 || 999999999999999 < value;
|
24505
|
-
}
|
24506
|
-
|
24507
23632
|
// 4.1.4. Serializing an Integer
|
24508
23633
|
//
|
24509
23634
|
// Given an Integer as input_integer, return an ASCII string suitable
|
@@ -24569,8 +23694,6 @@
|
|
24569
23694
|
}
|
24570
23695
|
}
|
24571
23696
|
|
24572
|
-
var DECIMAL = 'Decimal';
|
24573
|
-
|
24574
23697
|
// 4.1.5. Serializing a Decimal
|
24575
23698
|
//
|
24576
23699
|
// Given a decimal number as input_decimal, return an ASCII string
|
@@ -24616,8 +23739,6 @@
|
|
24616
23739
|
|
24617
23740
|
var STRING = 'String';
|
24618
23741
|
|
24619
|
-
var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
|
24620
|
-
|
24621
23742
|
// 4.1.6. Serializing a String
|
24622
23743
|
//
|
24623
23744
|
// Given a String as input_string, return an ASCII string suitable for
|
@@ -24653,8 +23774,6 @@
|
|
24653
23774
|
return symbol.description || symbol.toString().slice(7, -1);
|
24654
23775
|
}
|
24655
23776
|
|
24656
|
-
var TOKEN = 'Token';
|
24657
|
-
|
24658
23777
|
function serializeToken(token) {
|
24659
23778
|
var value = symbolToStr(token);
|
24660
23779
|
if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
|
@@ -24722,8 +23841,6 @@
|
|
24722
23841
|
}
|
24723
23842
|
}
|
24724
23843
|
|
24725
|
-
var KEY = 'Key';
|
24726
|
-
|
24727
23844
|
// 4.1.1.3. Serializing a Key
|
24728
23845
|
//
|
24729
23846
|
// Given a key as input_key, return an ASCII string suitable for use in
|
@@ -24975,6 +24092,36 @@
|
|
24975
24092
|
return toPath.join('/');
|
24976
24093
|
}
|
24977
24094
|
|
24095
|
+
/**
|
24096
|
+
* Generate a random v4 UUID
|
24097
|
+
*
|
24098
|
+
* @returns A random v4 UUID
|
24099
|
+
*
|
24100
|
+
* @group Utils
|
24101
|
+
*
|
24102
|
+
* @beta
|
24103
|
+
*/
|
24104
|
+
function uuid() {
|
24105
|
+
try {
|
24106
|
+
return crypto.randomUUID();
|
24107
|
+
} catch (error) {
|
24108
|
+
try {
|
24109
|
+
var url = URL.createObjectURL(new Blob());
|
24110
|
+
var _uuid = url.toString();
|
24111
|
+
URL.revokeObjectURL(url);
|
24112
|
+
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
24113
|
+
} catch (error) {
|
24114
|
+
var dt = new Date().getTime();
|
24115
|
+
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
24116
|
+
var r = (dt + Math.random() * 16) % 16 | 0;
|
24117
|
+
dt = Math.floor(dt / 16);
|
24118
|
+
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
24119
|
+
});
|
24120
|
+
return _uuid2;
|
24121
|
+
}
|
24122
|
+
}
|
24123
|
+
}
|
24124
|
+
|
24978
24125
|
var toRounded = function toRounded(value) {
|
24979
24126
|
return Math.round(value);
|
24980
24127
|
};
|
@@ -25219,36 +24366,6 @@
|
|
25219
24366
|
return "" + url + separator + query;
|
25220
24367
|
}
|
25221
24368
|
|
25222
|
-
/**
|
25223
|
-
* Generate a random v4 UUID
|
25224
|
-
*
|
25225
|
-
* @returns A random v4 UUID
|
25226
|
-
*
|
25227
|
-
* @group Utils
|
25228
|
-
*
|
25229
|
-
* @beta
|
25230
|
-
*/
|
25231
|
-
function uuid() {
|
25232
|
-
try {
|
25233
|
-
return crypto.randomUUID();
|
25234
|
-
} catch (error) {
|
25235
|
-
try {
|
25236
|
-
var url = URL.createObjectURL(new Blob());
|
25237
|
-
var _uuid = url.toString();
|
25238
|
-
URL.revokeObjectURL(url);
|
25239
|
-
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
25240
|
-
} catch (error) {
|
25241
|
-
var dt = new Date().getTime();
|
25242
|
-
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
25243
|
-
var r = (dt + Math.random() * 16) % 16 | 0;
|
25244
|
-
dt = Math.floor(dt / 16);
|
25245
|
-
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
25246
|
-
});
|
25247
|
-
return _uuid2;
|
25248
|
-
}
|
25249
|
-
}
|
25250
|
-
}
|
25251
|
-
|
25252
24369
|
/**
|
25253
24370
|
* Controller to deal with Common Media Client Data (CMCD)
|
25254
24371
|
* @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
|
@@ -25293,7 +24410,7 @@
|
|
25293
24410
|
su: !_this.initialized
|
25294
24411
|
});
|
25295
24412
|
} catch (error) {
|
25296
|
-
|
24413
|
+
logger.warn('Could not generate manifest CMCD data.', error);
|
25297
24414
|
}
|
25298
24415
|
};
|
25299
24416
|
/**
|
@@ -25313,15 +24430,9 @@
|
|
25313
24430
|
data.tb = _this.getTopBandwidth(ot) / 1000;
|
25314
24431
|
data.bl = _this.getBufferLength(ot);
|
25315
24432
|
}
|
25316
|
-
var next = _this.getNextFrag(fragment);
|
25317
|
-
if (next) {
|
25318
|
-
if (next.url && next.url !== fragment.url) {
|
25319
|
-
data.nor = next.url;
|
25320
|
-
}
|
25321
|
-
}
|
25322
24433
|
_this.apply(context, data);
|
25323
24434
|
} catch (error) {
|
25324
|
-
|
24435
|
+
logger.warn('Could not generate segment CMCD data.', error);
|
25325
24436
|
}
|
25326
24437
|
};
|
25327
24438
|
this.hls = hls;
|
@@ -25413,7 +24524,7 @@
|
|
25413
24524
|
data.su = this.buffering;
|
25414
24525
|
}
|
25415
24526
|
|
25416
|
-
// TODO: Implement rtp, nrr, dl
|
24527
|
+
// TODO: Implement rtp, nrr, nor, dl
|
25417
24528
|
|
25418
24529
|
var includeKeys = this.includeKeys;
|
25419
24530
|
if (includeKeys) {
|
@@ -25422,31 +24533,18 @@
|
|
25422
24533
|
return acc;
|
25423
24534
|
}, {});
|
25424
24535
|
}
|
25425
|
-
var options = {
|
25426
|
-
baseUrl: context.url
|
25427
|
-
};
|
25428
24536
|
if (this.useHeaders) {
|
25429
24537
|
if (!context.headers) {
|
25430
24538
|
context.headers = {};
|
25431
24539
|
}
|
25432
|
-
appendCmcdHeaders(context.headers, data
|
24540
|
+
appendCmcdHeaders(context.headers, data);
|
25433
24541
|
} else {
|
25434
|
-
context.url = appendCmcdQuery(context.url, data
|
24542
|
+
context.url = appendCmcdQuery(context.url, data);
|
25435
24543
|
}
|
25436
24544
|
};
|
25437
|
-
_proto.getNextFrag = function getNextFrag(fragment) {
|
25438
|
-
var _this$hls$levels$frag;
|
25439
|
-
var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
|
25440
|
-
if (levelDetails) {
|
25441
|
-
var index = fragment.sn - levelDetails.startSN;
|
25442
|
-
return levelDetails.fragments[index + 1];
|
25443
|
-
}
|
25444
|
-
return undefined;
|
25445
|
-
}
|
25446
|
-
|
25447
24545
|
/**
|
25448
24546
|
* The CMCD object type.
|
25449
|
-
|
24547
|
+
*/
|
25450
24548
|
_proto.getObjectType = function getObjectType(fragment) {
|
25451
24549
|
var type = fragment.type;
|
25452
24550
|
if (type === 'subtitle') {
|
@@ -25582,28 +24680,26 @@
|
|
25582
24680
|
}();
|
25583
24681
|
|
25584
24682
|
var PATHWAY_PENALTY_DURATION_MS = 300000;
|
25585
|
-
var ContentSteeringController = /*#__PURE__*/function (
|
25586
|
-
_inheritsLoose(ContentSteeringController, _Logger);
|
24683
|
+
var ContentSteeringController = /*#__PURE__*/function () {
|
25587
24684
|
function ContentSteeringController(hls) {
|
25588
|
-
|
25589
|
-
|
25590
|
-
|
25591
|
-
|
25592
|
-
|
25593
|
-
|
25594
|
-
|
25595
|
-
|
25596
|
-
|
25597
|
-
|
25598
|
-
|
25599
|
-
|
25600
|
-
|
25601
|
-
|
25602
|
-
|
25603
|
-
|
25604
|
-
|
25605
|
-
|
25606
|
-
return _this;
|
24685
|
+
this.hls = void 0;
|
24686
|
+
this.log = void 0;
|
24687
|
+
this.loader = null;
|
24688
|
+
this.uri = null;
|
24689
|
+
this.pathwayId = '.';
|
24690
|
+
this.pathwayPriority = null;
|
24691
|
+
this.timeToLoad = 300;
|
24692
|
+
this.reloadTimer = -1;
|
24693
|
+
this.updated = 0;
|
24694
|
+
this.started = false;
|
24695
|
+
this.enabled = true;
|
24696
|
+
this.levels = null;
|
24697
|
+
this.audioTracks = null;
|
24698
|
+
this.subtitleTracks = null;
|
24699
|
+
this.penalizedPathways = {};
|
24700
|
+
this.hls = hls;
|
24701
|
+
this.log = logger.log.bind(logger, "[content-steering]:");
|
24702
|
+
this.registerListeners();
|
25607
24703
|
}
|
25608
24704
|
var _proto = ContentSteeringController.prototype;
|
25609
24705
|
_proto.registerListeners = function registerListeners() {
|
@@ -25724,7 +24820,7 @@
|
|
25724
24820
|
errorAction.resolved = this.pathwayId !== errorPathway;
|
25725
24821
|
}
|
25726
24822
|
if (!errorAction.resolved) {
|
25727
|
-
|
24823
|
+
logger.warn("Could not resolve " + data.details + " (\"" + data.error.message + "\") with content-steering for Pathway: " + errorPathway + " levels: " + (levels ? levels.length : levels) + " priorities: " + JSON.stringify(pathwayPriority) + " penalized: " + JSON.stringify(this.penalizedPathways));
|
25728
24824
|
}
|
25729
24825
|
}
|
25730
24826
|
};
|
@@ -25804,7 +24900,7 @@
|
|
25804
24900
|
return defaultPathway;
|
25805
24901
|
};
|
25806
24902
|
_proto.clonePathways = function clonePathways(pathwayClones) {
|
25807
|
-
var
|
24903
|
+
var _this = this;
|
25808
24904
|
var levels = this.levels;
|
25809
24905
|
if (!levels) {
|
25810
24906
|
return;
|
@@ -25820,7 +24916,7 @@
|
|
25820
24916
|
})) {
|
25821
24917
|
return;
|
25822
24918
|
}
|
25823
|
-
var clonedVariants =
|
24919
|
+
var clonedVariants = _this.getLevelsForPathway(baseId).map(function (baseLevel) {
|
25824
24920
|
var attributes = new AttrList(baseLevel.attrs);
|
25825
24921
|
attributes['PATHWAY-ID'] = cloneId;
|
25826
24922
|
var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
|
@@ -25857,12 +24953,12 @@
|
|
25857
24953
|
return clonedLevel;
|
25858
24954
|
});
|
25859
24955
|
levels.push.apply(levels, clonedVariants);
|
25860
|
-
cloneRenditionGroups(
|
25861
|
-
cloneRenditionGroups(
|
24956
|
+
cloneRenditionGroups(_this.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
|
24957
|
+
cloneRenditionGroups(_this.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
|
25862
24958
|
});
|
25863
24959
|
};
|
25864
24960
|
_proto.loadSteeringManifest = function loadSteeringManifest(uri) {
|
25865
|
-
var
|
24961
|
+
var _this2 = this;
|
25866
24962
|
var config = this.hls.config;
|
25867
24963
|
var Loader = config.loader;
|
25868
24964
|
if (this.loader) {
|
@@ -25897,87 +24993,87 @@
|
|
25897
24993
|
};
|
25898
24994
|
var callbacks = {
|
25899
24995
|
onSuccess: function onSuccess(response, stats, context, networkDetails) {
|
25900
|
-
|
24996
|
+
_this2.log("Loaded steering manifest: \"" + url + "\"");
|
25901
24997
|
var steeringData = response.data;
|
25902
|
-
if (
|
25903
|
-
|
24998
|
+
if (steeringData.VERSION !== 1) {
|
24999
|
+
_this2.log("Steering VERSION " + steeringData.VERSION + " not supported!");
|
25904
25000
|
return;
|
25905
25001
|
}
|
25906
|
-
|
25907
|
-
|
25002
|
+
_this2.updated = performance.now();
|
25003
|
+
_this2.timeToLoad = steeringData.TTL;
|
25908
25004
|
var reloadUri = steeringData['RELOAD-URI'],
|
25909
25005
|
pathwayClones = steeringData['PATHWAY-CLONES'],
|
25910
25006
|
pathwayPriority = steeringData['PATHWAY-PRIORITY'];
|
25911
25007
|
if (reloadUri) {
|
25912
25008
|
try {
|
25913
|
-
|
25009
|
+
_this2.uri = new self.URL(reloadUri, url).href;
|
25914
25010
|
} catch (error) {
|
25915
|
-
|
25916
|
-
|
25011
|
+
_this2.enabled = false;
|
25012
|
+
_this2.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
|
25917
25013
|
return;
|
25918
25014
|
}
|
25919
25015
|
}
|
25920
|
-
|
25016
|
+
_this2.scheduleRefresh(_this2.uri || context.url);
|
25921
25017
|
if (pathwayClones) {
|
25922
|
-
|
25018
|
+
_this2.clonePathways(pathwayClones);
|
25923
25019
|
}
|
25924
25020
|
var loadedSteeringData = {
|
25925
25021
|
steeringManifest: steeringData,
|
25926
25022
|
url: url.toString()
|
25927
25023
|
};
|
25928
|
-
|
25024
|
+
_this2.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
|
25929
25025
|
if (pathwayPriority) {
|
25930
|
-
|
25026
|
+
_this2.updatePathwayPriority(pathwayPriority);
|
25931
25027
|
}
|
25932
25028
|
},
|
25933
25029
|
onError: function onError(error, context, networkDetails, stats) {
|
25934
|
-
|
25935
|
-
|
25030
|
+
_this2.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
|
25031
|
+
_this2.stopLoad();
|
25936
25032
|
if (error.code === 410) {
|
25937
|
-
|
25938
|
-
|
25033
|
+
_this2.enabled = false;
|
25034
|
+
_this2.log("Steering manifest " + context.url + " no longer available");
|
25939
25035
|
return;
|
25940
25036
|
}
|
25941
|
-
var ttl =
|
25037
|
+
var ttl = _this2.timeToLoad * 1000;
|
25942
25038
|
if (error.code === 429) {
|
25943
|
-
var loader =
|
25039
|
+
var loader = _this2.loader;
|
25944
25040
|
if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
|
25945
25041
|
var retryAfter = loader.getResponseHeader('Retry-After');
|
25946
25042
|
if (retryAfter) {
|
25947
25043
|
ttl = parseFloat(retryAfter) * 1000;
|
25948
25044
|
}
|
25949
25045
|
}
|
25950
|
-
|
25046
|
+
_this2.log("Steering manifest " + context.url + " rate limited");
|
25951
25047
|
return;
|
25952
25048
|
}
|
25953
|
-
|
25049
|
+
_this2.scheduleRefresh(_this2.uri || context.url, ttl);
|
25954
25050
|
},
|
25955
25051
|
onTimeout: function onTimeout(stats, context, networkDetails) {
|
25956
|
-
|
25957
|
-
|
25052
|
+
_this2.log("Timeout loading steering manifest (" + context.url + ")");
|
25053
|
+
_this2.scheduleRefresh(_this2.uri || context.url);
|
25958
25054
|
}
|
25959
25055
|
};
|
25960
25056
|
this.log("Requesting steering manifest: " + url);
|
25961
25057
|
this.loader.load(context, loaderConfig, callbacks);
|
25962
25058
|
};
|
25963
25059
|
_proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
|
25964
|
-
var
|
25060
|
+
var _this3 = this;
|
25965
25061
|
if (ttlMs === void 0) {
|
25966
25062
|
ttlMs = this.timeToLoad * 1000;
|
25967
25063
|
}
|
25968
25064
|
this.clearTimeout();
|
25969
25065
|
this.reloadTimer = self.setTimeout(function () {
|
25970
|
-
var
|
25971
|
-
var media = (
|
25066
|
+
var _this3$hls;
|
25067
|
+
var media = (_this3$hls = _this3.hls) == null ? void 0 : _this3$hls.media;
|
25972
25068
|
if (media && !media.ended) {
|
25973
|
-
|
25069
|
+
_this3.loadSteeringManifest(uri);
|
25974
25070
|
return;
|
25975
25071
|
}
|
25976
|
-
|
25072
|
+
_this3.scheduleRefresh(uri, _this3.timeToLoad * 1000);
|
25977
25073
|
}, ttlMs);
|
25978
25074
|
};
|
25979
25075
|
return ContentSteeringController;
|
25980
|
-
}(
|
25076
|
+
}();
|
25981
25077
|
function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
|
25982
25078
|
if (!tracks) {
|
25983
25079
|
return;
|
@@ -26877,7 +25973,7 @@
|
|
26877
25973
|
/**
|
26878
25974
|
* @ignore
|
26879
25975
|
*/
|
26880
|
-
function mergeConfig(defaultConfig, userConfig
|
25976
|
+
function mergeConfig(defaultConfig, userConfig) {
|
26881
25977
|
if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
|
26882
25978
|
throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
|
26883
25979
|
}
|
@@ -26947,7 +26043,7 @@
|
|
26947
26043
|
/**
|
26948
26044
|
* @ignore
|
26949
26045
|
*/
|
26950
|
-
function enableStreamingMode(config
|
26046
|
+
function enableStreamingMode(config) {
|
26951
26047
|
var currentLoader = config.loader;
|
26952
26048
|
if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
|
26953
26049
|
// If a developer has configured their own loader, respect that choice
|
@@ -26964,11 +26060,12 @@
|
|
26964
26060
|
}
|
26965
26061
|
}
|
26966
26062
|
|
26063
|
+
var chromeOrFirefox;
|
26967
26064
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
26968
26065
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
26969
26066
|
function LevelController(hls, contentSteeringController) {
|
26970
26067
|
var _this;
|
26971
|
-
_this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
|
26068
|
+
_this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this;
|
26972
26069
|
_this._levels = [];
|
26973
26070
|
_this._firstLevel = -1;
|
26974
26071
|
_this._maxAutoLevel = -1;
|
@@ -27037,13 +26134,21 @@
|
|
27037
26134
|
var videoCodecFound = false;
|
27038
26135
|
var audioCodecFound = false;
|
27039
26136
|
data.levels.forEach(function (levelParsed) {
|
27040
|
-
var _videoCodec;
|
26137
|
+
var _audioCodec, _videoCodec;
|
27041
26138
|
var attributes = levelParsed.attrs;
|
26139
|
+
|
26140
|
+
// erase audio codec info if browser does not support mp4a.40.34.
|
26141
|
+
// demuxer will autodetect codec and fallback to mpeg/audio
|
27042
26142
|
var audioCodec = levelParsed.audioCodec,
|
27043
26143
|
videoCodec = levelParsed.videoCodec;
|
26144
|
+
if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
|
26145
|
+
chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
|
26146
|
+
if (chromeOrFirefox) {
|
26147
|
+
levelParsed.audioCodec = audioCodec = undefined;
|
26148
|
+
}
|
26149
|
+
}
|
27044
26150
|
if (audioCodec) {
|
27045
|
-
|
27046
|
-
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
26151
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
|
27047
26152
|
}
|
27048
26153
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
27049
26154
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -27275,12 +26380,7 @@
|
|
27275
26380
|
if (curLevel.fragmentError === 0) {
|
27276
26381
|
curLevel.loadError = 0;
|
27277
26382
|
}
|
27278
|
-
|
27279
|
-
var previousDetails = curLevel.details;
|
27280
|
-
if (previousDetails === data.details && previousDetails.advanced) {
|
27281
|
-
previousDetails = undefined;
|
27282
|
-
}
|
27283
|
-
this.playlistLoaded(level, data, previousDetails);
|
26383
|
+
this.playlistLoaded(level, data, curLevel.details);
|
27284
26384
|
} else if ((_data$deliveryDirecti2 = data.deliveryDirectives) != null && _data$deliveryDirecti2.skip) {
|
27285
26385
|
// received a delta playlist update that cannot be merged
|
27286
26386
|
details.deltaUpdateFailed = true;
|
@@ -27656,8 +26756,6 @@
|
|
27656
26756
|
}
|
27657
26757
|
return this.loadKeyEME(keyInfo, frag);
|
27658
26758
|
case 'AES-128':
|
27659
|
-
case 'AES-256':
|
27660
|
-
case 'AES-256-CTR':
|
27661
26759
|
return this.loadKeyHTTP(keyInfo, frag);
|
27662
26760
|
default:
|
27663
26761
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -27797,26 +26895,21 @@
|
|
27797
26895
|
var MAX_START_GAP_JUMP = 2.0;
|
27798
26896
|
var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
|
27799
26897
|
var SKIP_BUFFER_RANGE_START = 0.05;
|
27800
|
-
var GapController = /*#__PURE__*/function (
|
27801
|
-
_inheritsLoose(GapController, _Logger);
|
26898
|
+
var GapController = /*#__PURE__*/function () {
|
27802
26899
|
function GapController(config, media, fragmentTracker, hls) {
|
27803
|
-
|
27804
|
-
|
27805
|
-
|
27806
|
-
|
27807
|
-
|
27808
|
-
|
27809
|
-
|
27810
|
-
|
27811
|
-
|
27812
|
-
|
27813
|
-
|
27814
|
-
|
27815
|
-
|
27816
|
-
_this.media = media;
|
27817
|
-
_this.fragmentTracker = fragmentTracker;
|
27818
|
-
_this.hls = hls;
|
27819
|
-
return _this;
|
26900
|
+
this.config = void 0;
|
26901
|
+
this.media = null;
|
26902
|
+
this.fragmentTracker = void 0;
|
26903
|
+
this.hls = void 0;
|
26904
|
+
this.nudgeRetry = 0;
|
26905
|
+
this.stallReported = false;
|
26906
|
+
this.stalled = null;
|
26907
|
+
this.moved = false;
|
26908
|
+
this.seeking = false;
|
26909
|
+
this.config = config;
|
26910
|
+
this.media = media;
|
26911
|
+
this.fragmentTracker = fragmentTracker;
|
26912
|
+
this.hls = hls;
|
27820
26913
|
}
|
27821
26914
|
var _proto = GapController.prototype;
|
27822
26915
|
_proto.destroy = function destroy() {
|
@@ -27831,7 +26924,7 @@
|
|
27831
26924
|
*
|
27832
26925
|
* @param lastCurrentTime - Previously read playhead position
|
27833
26926
|
*/;
|
27834
|
-
_proto.poll = function poll(lastCurrentTime, activeFrag
|
26927
|
+
_proto.poll = function poll(lastCurrentTime, activeFrag) {
|
27835
26928
|
var config = this.config,
|
27836
26929
|
media = this.media,
|
27837
26930
|
stalled = this.stalled;
|
@@ -27846,7 +26939,6 @@
|
|
27846
26939
|
|
27847
26940
|
// The playhead is moving, no-op
|
27848
26941
|
if (currentTime !== lastCurrentTime) {
|
27849
|
-
this.ended = 0;
|
27850
26942
|
this.moved = true;
|
27851
26943
|
if (!seeking) {
|
27852
26944
|
this.nudgeRetry = 0;
|
@@ -27855,7 +26947,7 @@
|
|
27855
26947
|
// The playhead is now moving, but was previously stalled
|
27856
26948
|
if (this.stallReported) {
|
27857
26949
|
var _stalledDuration = self.performance.now() - stalled;
|
27858
|
-
|
26950
|
+
logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
|
27859
26951
|
this.stallReported = false;
|
27860
26952
|
}
|
27861
26953
|
this.stalled = null;
|
@@ -27891,6 +26983,7 @@
|
|
27891
26983
|
// Skip start gaps if we haven't played, but the last poll detected the start of a stall
|
27892
26984
|
// The addition poll gives the browser a chance to jump the gap for us
|
27893
26985
|
if (!this.moved && this.stalled !== null) {
|
26986
|
+
var _level$details;
|
27894
26987
|
// There is no playable buffer (seeked, waiting for buffer)
|
27895
26988
|
var isBuffered = bufferInfo.len > 0;
|
27896
26989
|
if (!isBuffered && !nextStart) {
|
@@ -27902,8 +26995,9 @@
|
|
27902
26995
|
// When joining a live stream with audio tracks, account for live playlist window sliding by allowing
|
27903
26996
|
// a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
|
27904
26997
|
// that begins over 1 target duration after the video start position.
|
27905
|
-
var
|
27906
|
-
var
|
26998
|
+
var level = this.hls.levels ? this.hls.levels[this.hls.currentLevel] : null;
|
26999
|
+
var isLive = level == null ? void 0 : (_level$details = level.details) == null ? void 0 : _level$details.live;
|
27000
|
+
var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP;
|
27907
27001
|
var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
|
27908
27002
|
if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
|
27909
27003
|
if (!media.paused) {
|
@@ -27921,17 +27015,6 @@
|
|
27921
27015
|
}
|
27922
27016
|
var stalledDuration = tnow - stalled;
|
27923
27017
|
if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
|
27924
|
-
// Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
|
27925
|
-
if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
|
27926
|
-
if (stalledDuration < 1000 || this.ended) {
|
27927
|
-
return;
|
27928
|
-
}
|
27929
|
-
this.ended = currentTime;
|
27930
|
-
this.hls.trigger(Events.MEDIA_ENDED, {
|
27931
|
-
stalled: true
|
27932
|
-
});
|
27933
|
-
return;
|
27934
|
-
}
|
27935
27018
|
// Report stalling after trying to fix
|
27936
27019
|
this._reportStall(bufferInfo);
|
27937
27020
|
if (!this.media) {
|
@@ -27973,7 +27056,7 @@
|
|
27973
27056
|
// needs to cross some sort of threshold covering all source-buffers content
|
27974
27057
|
// to start playing properly.
|
27975
27058
|
if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
|
27976
|
-
|
27059
|
+
logger.warn('Trying to nudge playhead over buffer-hole');
|
27977
27060
|
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
|
27978
27061
|
// We only try to jump the hole if it's under the configured size
|
27979
27062
|
// Reset stalled so to rearm watchdog timer
|
@@ -27995,7 +27078,7 @@
|
|
27995
27078
|
// Report stalled error once
|
27996
27079
|
this.stallReported = true;
|
27997
27080
|
var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
|
27998
|
-
|
27081
|
+
logger.warn(error.message);
|
27999
27082
|
hls.trigger(Events.ERROR, {
|
28000
27083
|
type: ErrorTypes.MEDIA_ERROR,
|
28001
27084
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -28059,7 +27142,7 @@
|
|
28059
27142
|
}
|
28060
27143
|
}
|
28061
27144
|
var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
|
28062
|
-
|
27145
|
+
logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
|
28063
27146
|
this.moved = true;
|
28064
27147
|
this.stalled = null;
|
28065
27148
|
media.currentTime = targetTime;
|
@@ -28098,7 +27181,7 @@
|
|
28098
27181
|
var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
|
28099
27182
|
// playback stalled in buffered area ... let's nudge currentTime to try to overcome this
|
28100
27183
|
var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
|
28101
|
-
|
27184
|
+
logger.warn(error.message);
|
28102
27185
|
media.currentTime = targetTime;
|
28103
27186
|
hls.trigger(Events.ERROR, {
|
28104
27187
|
type: ErrorTypes.MEDIA_ERROR,
|
@@ -28108,7 +27191,7 @@
|
|
28108
27191
|
});
|
28109
27192
|
} else {
|
28110
27193
|
var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
|
28111
|
-
|
27194
|
+
logger.error(_error.message);
|
28112
27195
|
hls.trigger(Events.ERROR, {
|
28113
27196
|
type: ErrorTypes.MEDIA_ERROR,
|
28114
27197
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -28118,14 +27201,14 @@
|
|
28118
27201
|
}
|
28119
27202
|
};
|
28120
27203
|
return GapController;
|
28121
|
-
}(
|
27204
|
+
}();
|
28122
27205
|
|
28123
27206
|
var TICK_INTERVAL = 100; // how often to tick in ms
|
28124
27207
|
var StreamController = /*#__PURE__*/function (_BaseStreamController) {
|
28125
27208
|
_inheritsLoose(StreamController, _BaseStreamController);
|
28126
27209
|
function StreamController(hls, fragmentTracker, keyLoader) {
|
28127
27210
|
var _this;
|
28128
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
|
27211
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]', PlaylistLevelType.MAIN) || this;
|
28129
27212
|
_this.audioCodecSwap = false;
|
28130
27213
|
_this.gapController = null;
|
28131
27214
|
_this.level = -1;
|
@@ -28133,43 +27216,27 @@
|
|
28133
27216
|
_this.altAudio = false;
|
28134
27217
|
_this.audioOnly = false;
|
28135
27218
|
_this.fragPlaying = null;
|
27219
|
+
_this.onvplaying = null;
|
27220
|
+
_this.onvseeked = null;
|
28136
27221
|
_this.fragLastKbps = 0;
|
28137
27222
|
_this.couldBacktrack = false;
|
28138
27223
|
_this.backtrackFragment = null;
|
28139
27224
|
_this.audioCodecSwitch = false;
|
28140
27225
|
_this.videoBuffer = null;
|
28141
|
-
_this.
|
28142
|
-
// tick to speed up FRAG_CHANGED triggering
|
28143
|
-
_this.tick();
|
28144
|
-
};
|
28145
|
-
_this.onMediaSeeked = function () {
|
28146
|
-
var media = _this.media;
|
28147
|
-
var currentTime = media ? media.currentTime : null;
|
28148
|
-
if (isFiniteNumber(currentTime)) {
|
28149
|
-
_this.log("Media seeked to " + currentTime.toFixed(3));
|
28150
|
-
}
|
28151
|
-
|
28152
|
-
// If seeked was issued before buffer was appended do not tick immediately
|
28153
|
-
var bufferInfo = _this.getMainFwdBufferInfo();
|
28154
|
-
if (bufferInfo === null || bufferInfo.len === 0) {
|
28155
|
-
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
28156
|
-
return;
|
28157
|
-
}
|
28158
|
-
|
28159
|
-
// tick to speed up FRAG_CHANGED triggering
|
28160
|
-
_this.tick();
|
28161
|
-
};
|
28162
|
-
_this.registerListeners();
|
27226
|
+
_this._registerListeners();
|
28163
27227
|
return _this;
|
28164
27228
|
}
|
28165
27229
|
var _proto = StreamController.prototype;
|
28166
|
-
_proto.
|
28167
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
27230
|
+
_proto._registerListeners = function _registerListeners() {
|
28168
27231
|
var hls = this.hls;
|
27232
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27233
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27234
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
28169
27235
|
hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
28170
27236
|
hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
|
28171
27237
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
28172
27238
|
hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27239
|
+
hls.on(Events.ERROR, this.onError, this);
|
28173
27240
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
28174
27241
|
hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
28175
27242
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -28177,12 +27244,15 @@
|
|
28177
27244
|
hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
|
28178
27245
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
28179
27246
|
};
|
28180
|
-
_proto.
|
28181
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
27247
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
28182
27248
|
var hls = this.hls;
|
27249
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27250
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27251
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
28183
27252
|
hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
28184
27253
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
28185
27254
|
hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27255
|
+
hls.off(Events.ERROR, this.onError, this);
|
28186
27256
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
28187
27257
|
hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
28188
27258
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -28191,9 +27261,7 @@
|
|
28191
27261
|
hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
28192
27262
|
};
|
28193
27263
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
28194
|
-
|
28195
|
-
this.onMediaPlaying = this.onMediaSeeked = null;
|
28196
|
-
this.unregisterListeners();
|
27264
|
+
this._unregisterListeners();
|
28197
27265
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
28198
27266
|
};
|
28199
27267
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -28302,7 +27370,7 @@
|
|
28302
27370
|
return;
|
28303
27371
|
}
|
28304
27372
|
var level = hls.nextLoadLevel;
|
28305
|
-
if (!
|
27373
|
+
if (!(levels != null && levels[level])) {
|
28306
27374
|
return;
|
28307
27375
|
}
|
28308
27376
|
var levelInfo = levels[level];
|
@@ -28508,15 +27576,18 @@
|
|
28508
27576
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
28509
27577
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
28510
27578
|
var media = data.media;
|
28511
|
-
|
28512
|
-
|
27579
|
+
this.onvplaying = this.onMediaPlaying.bind(this);
|
27580
|
+
this.onvseeked = this.onMediaSeeked.bind(this);
|
27581
|
+
media.addEventListener('playing', this.onvplaying);
|
27582
|
+
media.addEventListener('seeked', this.onvseeked);
|
28513
27583
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
28514
27584
|
};
|
28515
27585
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
28516
27586
|
var media = this.media;
|
28517
|
-
if (media) {
|
28518
|
-
media.removeEventListener('playing', this.
|
28519
|
-
media.removeEventListener('seeked', this.
|
27587
|
+
if (media && this.onvplaying && this.onvseeked) {
|
27588
|
+
media.removeEventListener('playing', this.onvplaying);
|
27589
|
+
media.removeEventListener('seeked', this.onvseeked);
|
27590
|
+
this.onvplaying = this.onvseeked = null;
|
28520
27591
|
this.videoBuffer = null;
|
28521
27592
|
}
|
28522
27593
|
this.fragPlaying = null;
|
@@ -28526,6 +27597,27 @@
|
|
28526
27597
|
}
|
28527
27598
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
28528
27599
|
};
|
27600
|
+
_proto.onMediaPlaying = function onMediaPlaying() {
|
27601
|
+
// tick to speed up FRAG_CHANGED triggering
|
27602
|
+
this.tick();
|
27603
|
+
};
|
27604
|
+
_proto.onMediaSeeked = function onMediaSeeked() {
|
27605
|
+
var media = this.media;
|
27606
|
+
var currentTime = media ? media.currentTime : null;
|
27607
|
+
if (isFiniteNumber(currentTime)) {
|
27608
|
+
this.log("Media seeked to " + currentTime.toFixed(3));
|
27609
|
+
}
|
27610
|
+
|
27611
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
27612
|
+
var bufferInfo = this.getMainFwdBufferInfo();
|
27613
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
27614
|
+
this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27615
|
+
return;
|
27616
|
+
}
|
27617
|
+
|
27618
|
+
// tick to speed up FRAG_CHANGED triggering
|
27619
|
+
this.tick();
|
27620
|
+
};
|
28529
27621
|
_proto.onManifestLoading = function onManifestLoading() {
|
28530
27622
|
// reset buffer on manifest loading
|
28531
27623
|
this.log('Trigger BUFFER_RESET');
|
@@ -28806,10 +27898,8 @@
|
|
28806
27898
|
}
|
28807
27899
|
if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
|
28808
27900
|
// Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
|
28809
|
-
var
|
28810
|
-
|
28811
|
-
var levelDetails = this.getLevelDetails();
|
28812
|
-
gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
|
27901
|
+
var activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;
|
27902
|
+
gapController.poll(this.lastCurrentTime, activeFrag);
|
28813
27903
|
}
|
28814
27904
|
this.lastCurrentTime = media.currentTime;
|
28815
27905
|
};
|
@@ -29274,12 +28364,9 @@
|
|
29274
28364
|
* The configuration object provided on player instantiation.
|
29275
28365
|
*/
|
29276
28366
|
this.userConfig = void 0;
|
29277
|
-
/**
|
29278
|
-
* The logger functions used by this player instance, configured on player instantiation.
|
29279
|
-
*/
|
29280
|
-
this.logger = void 0;
|
29281
28367
|
this.coreComponents = void 0;
|
29282
28368
|
this.networkControllers = void 0;
|
28369
|
+
this.started = false;
|
29283
28370
|
this._emitter = new EventEmitter();
|
29284
28371
|
this._autoLevelCapping = -1;
|
29285
28372
|
this._maxHdcpLevel = null;
|
@@ -29296,11 +28383,11 @@
|
|
29296
28383
|
this._media = null;
|
29297
28384
|
this.url = null;
|
29298
28385
|
this.triggeringException = void 0;
|
29299
|
-
|
29300
|
-
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig
|
28386
|
+
enableLogs(userConfig.debug || false, 'Hls instance');
|
28387
|
+
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
|
29301
28388
|
this.userConfig = userConfig;
|
29302
28389
|
if (config.progressive) {
|
29303
|
-
enableStreamingMode(config
|
28390
|
+
enableStreamingMode(config);
|
29304
28391
|
}
|
29305
28392
|
|
29306
28393
|
// core controllers and network loaders
|
@@ -29408,7 +28495,7 @@
|
|
29408
28495
|
try {
|
29409
28496
|
return this.emit(event, event, eventObject);
|
29410
28497
|
} catch (error) {
|
29411
|
-
|
28498
|
+
logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
29412
28499
|
// Prevent recursion in error event handlers that throw #5497
|
29413
28500
|
if (!this.triggeringException) {
|
29414
28501
|
this.triggeringException = true;
|
@@ -29434,7 +28521,7 @@
|
|
29434
28521
|
* Dispose of the instance
|
29435
28522
|
*/;
|
29436
28523
|
_proto.destroy = function destroy() {
|
29437
|
-
|
28524
|
+
logger.log('destroy');
|
29438
28525
|
this.trigger(Events.DESTROYING, undefined);
|
29439
28526
|
this.detachMedia();
|
29440
28527
|
this.removeAllListeners();
|
@@ -29459,7 +28546,7 @@
|
|
29459
28546
|
* Attaches Hls.js to a media element
|
29460
28547
|
*/;
|
29461
28548
|
_proto.attachMedia = function attachMedia(media) {
|
29462
|
-
|
28549
|
+
logger.log('attachMedia');
|
29463
28550
|
this._media = media;
|
29464
28551
|
this.trigger(Events.MEDIA_ATTACHING, {
|
29465
28552
|
media: media
|
@@ -29470,7 +28557,7 @@
|
|
29470
28557
|
* Detach Hls.js from the media
|
29471
28558
|
*/;
|
29472
28559
|
_proto.detachMedia = function detachMedia() {
|
29473
|
-
|
28560
|
+
logger.log('detachMedia');
|
29474
28561
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
29475
28562
|
this._media = null;
|
29476
28563
|
}
|
@@ -29487,7 +28574,7 @@
|
|
29487
28574
|
});
|
29488
28575
|
this._autoLevelCapping = -1;
|
29489
28576
|
this._maxHdcpLevel = null;
|
29490
|
-
|
28577
|
+
logger.log("loadSource:" + loadingSource);
|
29491
28578
|
if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
|
29492
28579
|
this.detachMedia();
|
29493
28580
|
this.attachMedia(media);
|
@@ -29509,7 +28596,8 @@
|
|
29509
28596
|
if (startPosition === void 0) {
|
29510
28597
|
startPosition = -1;
|
29511
28598
|
}
|
29512
|
-
|
28599
|
+
logger.log("startLoad(" + startPosition + ")");
|
28600
|
+
this.started = true;
|
29513
28601
|
this.networkControllers.forEach(function (controller) {
|
29514
28602
|
controller.startLoad(startPosition);
|
29515
28603
|
});
|
@@ -29519,31 +28607,34 @@
|
|
29519
28607
|
* Stop loading of any stream data.
|
29520
28608
|
*/;
|
29521
28609
|
_proto.stopLoad = function stopLoad() {
|
29522
|
-
|
28610
|
+
logger.log('stopLoad');
|
28611
|
+
this.started = false;
|
29523
28612
|
this.networkControllers.forEach(function (controller) {
|
29524
28613
|
controller.stopLoad();
|
29525
28614
|
});
|
29526
28615
|
}
|
29527
28616
|
|
29528
28617
|
/**
|
29529
|
-
* Resumes stream controller segment loading
|
28618
|
+
* Resumes stream controller segment loading if previously started.
|
29530
28619
|
*/;
|
29531
28620
|
_proto.resumeBuffering = function resumeBuffering() {
|
29532
|
-
this.
|
29533
|
-
|
29534
|
-
controller
|
29535
|
-
|
29536
|
-
|
28621
|
+
if (this.started) {
|
28622
|
+
this.networkControllers.forEach(function (controller) {
|
28623
|
+
if ('fragmentLoader' in controller) {
|
28624
|
+
controller.startLoad(-1);
|
28625
|
+
}
|
28626
|
+
});
|
28627
|
+
}
|
29537
28628
|
}
|
29538
28629
|
|
29539
28630
|
/**
|
29540
|
-
*
|
28631
|
+
* Stops stream controller segment loading without changing 'started' state like stopLoad().
|
29541
28632
|
* This allows for media buffering to be paused without interupting playlist loading.
|
29542
28633
|
*/;
|
29543
28634
|
_proto.pauseBuffering = function pauseBuffering() {
|
29544
28635
|
this.networkControllers.forEach(function (controller) {
|
29545
|
-
if (controller
|
29546
|
-
controller.
|
28636
|
+
if ('fragmentLoader' in controller) {
|
28637
|
+
controller.stopLoad();
|
29547
28638
|
}
|
29548
28639
|
});
|
29549
28640
|
}
|
@@ -29552,7 +28643,7 @@
|
|
29552
28643
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
29553
28644
|
*/;
|
29554
28645
|
_proto.swapAudioCodec = function swapAudioCodec() {
|
29555
|
-
|
28646
|
+
logger.log('swapAudioCodec');
|
29556
28647
|
this.streamController.swapAudioCodec();
|
29557
28648
|
}
|
29558
28649
|
|
@@ -29563,7 +28654,7 @@
|
|
29563
28654
|
* Automatic recovery of media-errors by this process is configurable.
|
29564
28655
|
*/;
|
29565
28656
|
_proto.recoverMediaError = function recoverMediaError() {
|
29566
|
-
|
28657
|
+
logger.log('recoverMediaError');
|
29567
28658
|
var media = this._media;
|
29568
28659
|
this.detachMedia();
|
29569
28660
|
if (media) {
|
@@ -29618,7 +28709,7 @@
|
|
29618
28709
|
* 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.
|
29619
28710
|
*/,
|
29620
28711
|
set: function set(newLevel) {
|
29621
|
-
|
28712
|
+
logger.log("set currentLevel:" + newLevel);
|
29622
28713
|
this.levelController.manualLevel = newLevel;
|
29623
28714
|
this.streamController.immediateLevelSwitch();
|
29624
28715
|
}
|
@@ -29639,7 +28730,7 @@
|
|
29639
28730
|
* @param newLevel - Pass -1 for automatic level selection
|
29640
28731
|
*/,
|
29641
28732
|
set: function set(newLevel) {
|
29642
|
-
|
28733
|
+
logger.log("set nextLevel:" + newLevel);
|
29643
28734
|
this.levelController.manualLevel = newLevel;
|
29644
28735
|
this.streamController.nextLevelSwitch();
|
29645
28736
|
}
|
@@ -29660,7 +28751,7 @@
|
|
29660
28751
|
* @param newLevel - Pass -1 for automatic level selection
|
29661
28752
|
*/,
|
29662
28753
|
set: function set(newLevel) {
|
29663
|
-
|
28754
|
+
logger.log("set loadLevel:" + newLevel);
|
29664
28755
|
this.levelController.manualLevel = newLevel;
|
29665
28756
|
}
|
29666
28757
|
|
@@ -29695,7 +28786,7 @@
|
|
29695
28786
|
* Sets "first-level", see getter.
|
29696
28787
|
*/,
|
29697
28788
|
set: function set(newLevel) {
|
29698
|
-
|
28789
|
+
logger.log("set firstLevel:" + newLevel);
|
29699
28790
|
this.levelController.firstLevel = newLevel;
|
29700
28791
|
}
|
29701
28792
|
|
@@ -29722,7 +28813,7 @@
|
|
29722
28813
|
* (determined from download of first segment)
|
29723
28814
|
*/,
|
29724
28815
|
set: function set(newLevel) {
|
29725
|
-
|
28816
|
+
logger.log("set startLevel:" + newLevel);
|
29726
28817
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
29727
28818
|
if (newLevel !== -1) {
|
29728
28819
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -29775,7 +28866,7 @@
|
|
29775
28866
|
*/
|
29776
28867
|
function set(newLevel) {
|
29777
28868
|
if (this._autoLevelCapping !== newLevel) {
|
29778
|
-
|
28869
|
+
logger.log("set autoLevelCapping:" + newLevel);
|
29779
28870
|
this._autoLevelCapping = newLevel;
|
29780
28871
|
this.levelController.checkMaxAutoUpdated();
|
29781
28872
|
}
|
@@ -30100,7 +29191,7 @@
|
|
30100
29191
|
* Get the video-dev/hls.js package version.
|
30101
29192
|
*/
|
30102
29193
|
function get() {
|
30103
|
-
return "1.5.6
|
29194
|
+
return "1.5.6";
|
30104
29195
|
}
|
30105
29196
|
}, {
|
30106
29197
|
key: "Events",
|