hls.js 1.5.5-0.canary.9997 → 1.5.5
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 +20 -20
- 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.5");
|
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.5-0.canary.9997");
|
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
|
|
@@ -2949,13 +2923,13 @@
|
|
2949
2923
|
this.keyFormatVersions = formatversions;
|
2950
2924
|
this.iv = iv;
|
2951
2925
|
this.encrypted = method ? method !== 'NONE' : false;
|
2952
|
-
this.isCommonEncryption = this.encrypted &&
|
2926
|
+
this.isCommonEncryption = this.encrypted && method !== 'AES-128';
|
2953
2927
|
}
|
2954
2928
|
var _proto = LevelKey.prototype;
|
2955
2929
|
_proto.isSupported = function isSupported() {
|
2956
2930
|
// If it's Segment encryption or No encryption, just select that key system
|
2957
2931
|
if (this.method) {
|
2958
|
-
if (
|
2932
|
+
if (this.method === 'AES-128' || this.method === 'NONE') {
|
2959
2933
|
return true;
|
2960
2934
|
}
|
2961
2935
|
if (this.keyFormat === 'identity') {
|
@@ -2977,13 +2951,14 @@
|
|
2977
2951
|
if (!this.encrypted || !this.uri) {
|
2978
2952
|
return null;
|
2979
2953
|
}
|
2980
|
-
if (
|
2954
|
+
if (this.method === 'AES-128' && this.uri && !this.iv) {
|
2981
2955
|
if (typeof sn !== 'number') {
|
2982
2956
|
// We are fetching decryption data for a initialization segment
|
2983
|
-
// If the segment was encrypted with AES-128
|
2957
|
+
// If the segment was encrypted with AES-128
|
2984
2958
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
2985
|
-
|
2986
|
-
|
2959
|
+
if (this.method === 'AES-128' && !this.iv) {
|
2960
|
+
logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
|
2961
|
+
}
|
2987
2962
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
2988
2963
|
sn = 0;
|
2989
2964
|
}
|
@@ -3277,28 +3252,23 @@
|
|
3277
3252
|
if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
|
3278
3253
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
|
3279
3254
|
}
|
3255
|
+
|
3256
|
+
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3257
|
+
// some browsers will report that fLaC is supported then fail.
|
3258
|
+
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3280
3259
|
var codecsToCheck = {
|
3281
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3282
|
-
// some browsers will report that fLaC is supported then fail.
|
3283
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3284
3260
|
flac: ['flac', 'fLaC', 'FLAC'],
|
3285
|
-
opus: ['opus', 'Opus']
|
3286
|
-
// Replace audio codec info if browser does not support mp4a.40.34,
|
3287
|
-
// and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
|
3288
|
-
'mp4a.40.34': ['mp3']
|
3261
|
+
opus: ['opus', 'Opus']
|
3289
3262
|
}[lowerCaseCodec];
|
3290
3263
|
for (var i = 0; i < codecsToCheck.length; i++) {
|
3291
|
-
var _getMediaSource;
|
3292
3264
|
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
|
3293
3265
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
3294
3266
|
return codecsToCheck[i];
|
3295
|
-
} else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
|
3296
|
-
return '';
|
3297
3267
|
}
|
3298
3268
|
}
|
3299
3269
|
return lowerCaseCodec;
|
3300
3270
|
}
|
3301
|
-
var AUDIO_CODEC_REGEXP = /flac|opus
|
3271
|
+
var AUDIO_CODEC_REGEXP = /flac|opus/i;
|
3302
3272
|
function getCodecCompatibleName(codec, preferManagedMediaSource) {
|
3303
3273
|
if (preferManagedMediaSource === void 0) {
|
3304
3274
|
preferManagedMediaSource = true;
|
@@ -3326,18 +3296,6 @@
|
|
3326
3296
|
}
|
3327
3297
|
return codec;
|
3328
3298
|
}
|
3329
|
-
function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
|
3330
|
-
var MediaSource = getMediaSource(preferManagedMediaSource) || {
|
3331
|
-
isTypeSupported: function isTypeSupported() {
|
3332
|
-
return false;
|
3333
|
-
}
|
3334
|
-
};
|
3335
|
-
return {
|
3336
|
-
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
3337
|
-
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
3338
|
-
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
3339
|
-
};
|
3340
|
-
}
|
3341
3299
|
|
3342
3300
|
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;
|
3343
3301
|
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
|
@@ -4187,10 +4145,10 @@
|
|
4187
4145
|
var loaderContext = loader.context;
|
4188
4146
|
if (loaderContext && loaderContext.url === context.url && loaderContext.level === context.level) {
|
4189
4147
|
// same URL can't overlap
|
4190
|
-
|
4148
|
+
logger.trace('[playlist-loader]: playlist request ongoing');
|
4191
4149
|
return;
|
4192
4150
|
}
|
4193
|
-
|
4151
|
+
logger.log("[playlist-loader]: aborting previous loader for type: " + context.type);
|
4194
4152
|
loader.abort();
|
4195
4153
|
}
|
4196
4154
|
|
@@ -4300,7 +4258,7 @@
|
|
4300
4258
|
// alt audio rendition in which quality levels (main)
|
4301
4259
|
// contains both audio+video. but with mixed audio track not signaled
|
4302
4260
|
if (!embeddedAudioFound && levels[0].audioCodec && !levels[0].attrs.AUDIO) {
|
4303
|
-
|
4261
|
+
logger.log('[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one');
|
4304
4262
|
audioTracks.unshift({
|
4305
4263
|
type: 'main',
|
4306
4264
|
name: 'main',
|
@@ -4400,7 +4358,7 @@
|
|
4400
4358
|
message += " id: " + context.id + " group-id: \"" + context.groupId + "\"";
|
4401
4359
|
}
|
4402
4360
|
var error = new Error(message);
|
4403
|
-
|
4361
|
+
logger.warn("[playlist-loader]: " + message);
|
4404
4362
|
var details = ErrorDetails.UNKNOWN;
|
4405
4363
|
var fatal = false;
|
4406
4364
|
var loader = this.getInternalLoader(context);
|
@@ -5001,43 +4959,8 @@
|
|
5001
4959
|
this.currentTime = 0;
|
5002
4960
|
this.stallCount = 0;
|
5003
4961
|
this._latency = null;
|
5004
|
-
this.
|
5005
|
-
|
5006
|
-
levelDetails = _this.levelDetails;
|
5007
|
-
if (!media || !levelDetails) {
|
5008
|
-
return;
|
5009
|
-
}
|
5010
|
-
_this.currentTime = media.currentTime;
|
5011
|
-
var latency = _this.computeLatency();
|
5012
|
-
if (latency === null) {
|
5013
|
-
return;
|
5014
|
-
}
|
5015
|
-
_this._latency = latency;
|
5016
|
-
|
5017
|
-
// Adapt playbackRate to meet target latency in low-latency mode
|
5018
|
-
var _this$config = _this.config,
|
5019
|
-
lowLatencyMode = _this$config.lowLatencyMode,
|
5020
|
-
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5021
|
-
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5022
|
-
return;
|
5023
|
-
}
|
5024
|
-
var targetLatency = _this.targetLatency;
|
5025
|
-
if (targetLatency === null) {
|
5026
|
-
return;
|
5027
|
-
}
|
5028
|
-
var distanceFromTarget = latency - targetLatency;
|
5029
|
-
// Only adjust playbackRate when within one target duration of targetLatency
|
5030
|
-
// and more than one second from under-buffering.
|
5031
|
-
// Playback further than one target duration from target can be considered DVR playback.
|
5032
|
-
var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
|
5033
|
-
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5034
|
-
if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
|
5035
|
-
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5036
|
-
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
|
5037
|
-
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5038
|
-
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5039
|
-
media.playbackRate = 1;
|
5040
|
-
}
|
4962
|
+
this.timeupdateHandler = function () {
|
4963
|
+
return _this.timeupdate();
|
5041
4964
|
};
|
5042
4965
|
this.hls = hls;
|
5043
4966
|
this.config = hls.config;
|
@@ -5049,7 +4972,7 @@
|
|
5049
4972
|
this.onMediaDetaching();
|
5050
4973
|
this.levelDetails = null;
|
5051
4974
|
// @ts-ignore
|
5052
|
-
this.hls = null;
|
4975
|
+
this.hls = this.timeupdateHandler = null;
|
5053
4976
|
};
|
5054
4977
|
_proto.registerListeners = function registerListeners() {
|
5055
4978
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -5067,11 +4990,11 @@
|
|
5067
4990
|
};
|
5068
4991
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
5069
4992
|
this.media = data.media;
|
5070
|
-
this.media.addEventListener('timeupdate', this.
|
4993
|
+
this.media.addEventListener('timeupdate', this.timeupdateHandler);
|
5071
4994
|
};
|
5072
4995
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
5073
4996
|
if (this.media) {
|
5074
|
-
this.media.removeEventListener('timeupdate', this.
|
4997
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5075
4998
|
this.media = null;
|
5076
4999
|
}
|
5077
5000
|
};
|
@@ -5084,10 +5007,10 @@
|
|
5084
5007
|
var details = _ref.details;
|
5085
5008
|
this.levelDetails = details;
|
5086
5009
|
if (details.advanced) {
|
5087
|
-
this.
|
5010
|
+
this.timeupdate();
|
5088
5011
|
}
|
5089
5012
|
if (!details.live && this.media) {
|
5090
|
-
this.media.removeEventListener('timeupdate', this.
|
5013
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5091
5014
|
}
|
5092
5015
|
};
|
5093
5016
|
_proto.onError = function onError(event, data) {
|
@@ -5097,7 +5020,45 @@
|
|
5097
5020
|
}
|
5098
5021
|
this.stallCount++;
|
5099
5022
|
if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
|
5100
|
-
|
5023
|
+
logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
|
5024
|
+
}
|
5025
|
+
};
|
5026
|
+
_proto.timeupdate = function timeupdate() {
|
5027
|
+
var media = this.media,
|
5028
|
+
levelDetails = this.levelDetails;
|
5029
|
+
if (!media || !levelDetails) {
|
5030
|
+
return;
|
5031
|
+
}
|
5032
|
+
this.currentTime = media.currentTime;
|
5033
|
+
var latency = this.computeLatency();
|
5034
|
+
if (latency === null) {
|
5035
|
+
return;
|
5036
|
+
}
|
5037
|
+
this._latency = latency;
|
5038
|
+
|
5039
|
+
// Adapt playbackRate to meet target latency in low-latency mode
|
5040
|
+
var _this$config = this.config,
|
5041
|
+
lowLatencyMode = _this$config.lowLatencyMode,
|
5042
|
+
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5043
|
+
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5044
|
+
return;
|
5045
|
+
}
|
5046
|
+
var targetLatency = this.targetLatency;
|
5047
|
+
if (targetLatency === null) {
|
5048
|
+
return;
|
5049
|
+
}
|
5050
|
+
var distanceFromTarget = latency - targetLatency;
|
5051
|
+
// Only adjust playbackRate when within one target duration of targetLatency
|
5052
|
+
// and more than one second from under-buffering.
|
5053
|
+
// Playback further than one target duration from target can be considered DVR playback.
|
5054
|
+
var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
|
5055
|
+
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5056
|
+
if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
|
5057
|
+
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5058
|
+
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
|
5059
|
+
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5060
|
+
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5061
|
+
media.playbackRate = 1;
|
5101
5062
|
}
|
5102
5063
|
};
|
5103
5064
|
_proto.estimateLiveEdge = function estimateLiveEdge() {
|
@@ -6005,17 +5966,19 @@
|
|
6005
5966
|
MoveAllAlternatesMatchingHDCP: 2,
|
6006
5967
|
SwitchToSDR: 4
|
6007
5968
|
}; // Reserved for future use
|
6008
|
-
var ErrorController = /*#__PURE__*/function (
|
6009
|
-
_inheritsLoose(ErrorController, _Logger);
|
5969
|
+
var ErrorController = /*#__PURE__*/function () {
|
6010
5970
|
function ErrorController(hls) {
|
6011
|
-
|
6012
|
-
|
6013
|
-
|
6014
|
-
|
6015
|
-
|
6016
|
-
|
6017
|
-
|
6018
|
-
|
5971
|
+
this.hls = void 0;
|
5972
|
+
this.playlistError = 0;
|
5973
|
+
this.penalizedRenditions = {};
|
5974
|
+
this.log = void 0;
|
5975
|
+
this.warn = void 0;
|
5976
|
+
this.error = void 0;
|
5977
|
+
this.hls = hls;
|
5978
|
+
this.log = logger.log.bind(logger, "[info]:");
|
5979
|
+
this.warn = logger.warn.bind(logger, "[warning]:");
|
5980
|
+
this.error = logger.error.bind(logger, "[error]:");
|
5981
|
+
this.registerListeners();
|
6019
5982
|
}
|
6020
5983
|
var _proto = ErrorController.prototype;
|
6021
5984
|
_proto.registerListeners = function registerListeners() {
|
@@ -6371,19 +6334,19 @@
|
|
6371
6334
|
}
|
6372
6335
|
};
|
6373
6336
|
return ErrorController;
|
6374
|
-
}(
|
6337
|
+
}();
|
6375
6338
|
|
6376
|
-
var BasePlaylistController = /*#__PURE__*/function (
|
6377
|
-
_inheritsLoose(BasePlaylistController, _Logger);
|
6339
|
+
var BasePlaylistController = /*#__PURE__*/function () {
|
6378
6340
|
function BasePlaylistController(hls, logPrefix) {
|
6379
|
-
|
6380
|
-
|
6381
|
-
|
6382
|
-
|
6383
|
-
|
6384
|
-
|
6385
|
-
|
6386
|
-
|
6341
|
+
this.hls = void 0;
|
6342
|
+
this.timer = -1;
|
6343
|
+
this.requestScheduled = -1;
|
6344
|
+
this.canLoad = false;
|
6345
|
+
this.log = void 0;
|
6346
|
+
this.warn = void 0;
|
6347
|
+
this.log = logger.log.bind(logger, logPrefix + ":");
|
6348
|
+
this.warn = logger.warn.bind(logger, logPrefix + ":");
|
6349
|
+
this.hls = hls;
|
6387
6350
|
}
|
6388
6351
|
var _proto = BasePlaylistController.prototype;
|
6389
6352
|
_proto.destroy = function destroy() {
|
@@ -6416,7 +6379,7 @@
|
|
6416
6379
|
try {
|
6417
6380
|
uri = new self.URL(attr.URI, previous.url).href;
|
6418
6381
|
} catch (error) {
|
6419
|
-
|
6382
|
+
logger.warn("Could not construct new URL for Rendition Report: " + error);
|
6420
6383
|
uri = attr.URI || '';
|
6421
6384
|
}
|
6422
6385
|
// Use exact match. Otherwise, the last partial match, if any, will be used
|
@@ -6455,7 +6418,7 @@
|
|
6455
6418
|
return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
|
6456
6419
|
};
|
6457
6420
|
_proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
|
6458
|
-
var
|
6421
|
+
var _this = this;
|
6459
6422
|
var details = data.details,
|
6460
6423
|
stats = data.stats;
|
6461
6424
|
|
@@ -6502,12 +6465,7 @@
|
|
6502
6465
|
var cdnAge = lastAdvanced + details.ageHeader;
|
6503
6466
|
var currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5);
|
6504
6467
|
if (currentGoal > 0) {
|
6505
|
-
if (
|
6506
|
-
// Omit segment and part directives when the last response was more than 3 target durations ago,
|
6507
|
-
this.log("Playlist last advanced " + lastAdvanced.toFixed(2) + "s ago. Omitting segment and part directives.");
|
6508
|
-
msn = undefined;
|
6509
|
-
part = undefined;
|
6510
|
-
} else if (previousDetails != null && previousDetails.tuneInGoal && cdnAge - details.partTarget > previousDetails.tuneInGoal) {
|
6468
|
+
if (previousDetails && currentGoal > previousDetails.tuneInGoal) {
|
6511
6469
|
// If we attempted to get the next or latest playlist update, but currentGoal increased,
|
6512
6470
|
// then we either can't catchup, or the "age" header cannot be trusted.
|
6513
6471
|
this.warn("CDN Tune-in goal increased from: " + previousDetails.tuneInGoal + " to: " + currentGoal + " with playlist age: " + details.age);
|
@@ -6565,7 +6523,7 @@
|
|
6565
6523
|
// );
|
6566
6524
|
|
6567
6525
|
this.timer = self.setTimeout(function () {
|
6568
|
-
return
|
6526
|
+
return _this.loadPlaylist(deliveryDirectives);
|
6569
6527
|
}, estimatedTimeUntilUpdate);
|
6570
6528
|
} else {
|
6571
6529
|
this.clearTimer();
|
@@ -6581,7 +6539,7 @@
|
|
6581
6539
|
return new HlsUrlParameters(msn, part, skip);
|
6582
6540
|
};
|
6583
6541
|
_proto.checkRetry = function checkRetry(errorEvent) {
|
6584
|
-
var
|
6542
|
+
var _this2 = this;
|
6585
6543
|
var errorDetails = errorEvent.details;
|
6586
6544
|
var isTimeout = isTimeoutError(errorEvent);
|
6587
6545
|
var errorAction = errorEvent.errorAction;
|
@@ -6605,7 +6563,7 @@
|
|
6605
6563
|
var delay = getRetryDelay(retryConfig, retryCount);
|
6606
6564
|
// Schedule level/track reload
|
6607
6565
|
this.timer = self.setTimeout(function () {
|
6608
|
-
return
|
6566
|
+
return _this2.loadPlaylist();
|
6609
6567
|
}, delay);
|
6610
6568
|
this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
|
6611
6569
|
}
|
@@ -6616,7 +6574,7 @@
|
|
6616
6574
|
return retry;
|
6617
6575
|
};
|
6618
6576
|
return BasePlaylistController;
|
6619
|
-
}(
|
6577
|
+
}();
|
6620
6578
|
|
6621
6579
|
/*
|
6622
6580
|
* compute an Exponential Weighted moving average
|
@@ -7218,33 +7176,30 @@
|
|
7218
7176
|
return -1;
|
7219
7177
|
}
|
7220
7178
|
|
7221
|
-
var AbrController = /*#__PURE__*/function (
|
7222
|
-
_inheritsLoose(AbrController, _Logger);
|
7179
|
+
var AbrController = /*#__PURE__*/function () {
|
7223
7180
|
function AbrController(_hls) {
|
7224
|
-
var _this;
|
7225
|
-
|
7226
|
-
|
7227
|
-
|
7228
|
-
|
7229
|
-
|
7230
|
-
|
7231
|
-
|
7232
|
-
|
7233
|
-
|
7234
|
-
|
7235
|
-
|
7236
|
-
|
7237
|
-
|
7238
|
-
_this.bwEstimator = void 0;
|
7181
|
+
var _this = this;
|
7182
|
+
this.hls = void 0;
|
7183
|
+
this.lastLevelLoadSec = 0;
|
7184
|
+
this.lastLoadedFragLevel = -1;
|
7185
|
+
this.firstSelection = -1;
|
7186
|
+
this._nextAutoLevel = -1;
|
7187
|
+
this.nextAutoLevelKey = '';
|
7188
|
+
this.audioTracksByGroup = null;
|
7189
|
+
this.codecTiers = null;
|
7190
|
+
this.timer = -1;
|
7191
|
+
this.fragCurrent = null;
|
7192
|
+
this.partCurrent = null;
|
7193
|
+
this.bitrateTestDelay = 0;
|
7194
|
+
this.bwEstimator = void 0;
|
7239
7195
|
/*
|
7240
7196
|
This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
|
7241
7197
|
quickly enough to prevent underbuffering
|
7242
7198
|
*/
|
7243
|
-
|
7244
|
-
var
|
7245
|
-
|
7246
|
-
|
7247
|
-
hls = _assertThisInitialize.hls;
|
7199
|
+
this._abandonRulesCheck = function () {
|
7200
|
+
var frag = _this.fragCurrent,
|
7201
|
+
part = _this.partCurrent,
|
7202
|
+
hls = _this.hls;
|
7248
7203
|
var autoLevelEnabled = hls.autoLevelEnabled,
|
7249
7204
|
media = hls.media;
|
7250
7205
|
if (!frag || !media) {
|
@@ -7333,22 +7288,21 @@
|
|
7333
7288
|
_this.resetEstimator(nextLoadLevelBitrate);
|
7334
7289
|
}
|
7335
7290
|
_this.clearTimer();
|
7336
|
-
|
7291
|
+
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");
|
7337
7292
|
hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
|
7338
7293
|
frag: frag,
|
7339
7294
|
part: part,
|
7340
7295
|
stats: stats
|
7341
7296
|
});
|
7342
7297
|
};
|
7343
|
-
|
7344
|
-
|
7345
|
-
|
7346
|
-
return _this;
|
7298
|
+
this.hls = _hls;
|
7299
|
+
this.bwEstimator = this.initEstimator();
|
7300
|
+
this.registerListeners();
|
7347
7301
|
}
|
7348
7302
|
var _proto = AbrController.prototype;
|
7349
7303
|
_proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
|
7350
7304
|
if (abrEwmaDefaultEstimate) {
|
7351
|
-
|
7305
|
+
logger.log("setting initial bwe to " + abrEwmaDefaultEstimate);
|
7352
7306
|
this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
|
7353
7307
|
}
|
7354
7308
|
this.firstSelection = -1;
|
@@ -7600,13 +7554,13 @@
|
|
7600
7554
|
// cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
|
7601
7555
|
var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
|
7602
7556
|
maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
|
7603
|
-
|
7557
|
+
logger.info("[abr] bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
|
7604
7558
|
// don't use conservative factor on bitrate test
|
7605
7559
|
bwFactor = bwUpFactor = 1;
|
7606
7560
|
}
|
7607
7561
|
}
|
7608
7562
|
var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
|
7609
|
-
|
7563
|
+
logger.info("[abr] " + (bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
|
7610
7564
|
if (bestLevel > -1) {
|
7611
7565
|
return bestLevel;
|
7612
7566
|
}
|
@@ -7662,7 +7616,7 @@
|
|
7662
7616
|
currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
|
7663
7617
|
currentFrameRate = minFramerate;
|
7664
7618
|
currentBw = Math.max(currentBw, minBitrate);
|
7665
|
-
|
7619
|
+
logger.log("[abr] picked start tier " + JSON.stringify(startTier));
|
7666
7620
|
} else {
|
7667
7621
|
currentCodecSet = level == null ? void 0 : level.codecSet;
|
7668
7622
|
currentVideoRange = level == null ? void 0 : level.videoRange;
|
@@ -7686,11 +7640,11 @@
|
|
7686
7640
|
var levels = _this2.hls.levels;
|
7687
7641
|
var index = levels.indexOf(levelInfo);
|
7688
7642
|
if (decodingInfo.error) {
|
7689
|
-
|
7643
|
+
logger.warn("[abr] MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
|
7690
7644
|
} else if (!decodingInfo.supported) {
|
7691
|
-
|
7645
|
+
logger.warn("[abr] Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
|
7692
7646
|
if (index > -1 && levels.length > 1) {
|
7693
|
-
|
7647
|
+
logger.log("[abr] Removing unsupported level " + index);
|
7694
7648
|
_this2.hls.removeLevel(index);
|
7695
7649
|
}
|
7696
7650
|
}
|
@@ -7737,9 +7691,9 @@
|
|
7737
7691
|
var forcedAutoLevel = _this2.forcedAutoLevel;
|
7738
7692
|
if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
|
7739
7693
|
if (levelsSkipped.length) {
|
7740
|
-
|
7694
|
+
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);
|
7741
7695
|
}
|
7742
|
-
|
7696
|
+
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);
|
7743
7697
|
}
|
7744
7698
|
if (firstSelection) {
|
7745
7699
|
_this2.firstSelection = i;
|
@@ -7773,7 +7727,7 @@
|
|
7773
7727
|
}
|
7774
7728
|
var firstLevel = this.hls.firstLevel;
|
7775
7729
|
var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
|
7776
|
-
|
7730
|
+
logger.warn("[abr] Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
|
7777
7731
|
return clamped;
|
7778
7732
|
}
|
7779
7733
|
}, {
|
@@ -7826,7 +7780,7 @@
|
|
7826
7780
|
}
|
7827
7781
|
}]);
|
7828
7782
|
return AbrController;
|
7829
|
-
}(
|
7783
|
+
}();
|
7830
7784
|
|
7831
7785
|
/**
|
7832
7786
|
* @ignore
|
@@ -7857,17 +7811,13 @@
|
|
7857
7811
|
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
|
7858
7812
|
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
|
7859
7813
|
*/
|
7860
|
-
var TaskLoop = /*#__PURE__*/function (
|
7861
|
-
|
7862
|
-
|
7863
|
-
|
7864
|
-
|
7865
|
-
|
7866
|
-
|
7867
|
-
_this._tickInterval = null;
|
7868
|
-
_this._tickCallCount = 0;
|
7869
|
-
_this._boundTick = _this.tick.bind(_assertThisInitialized(_this));
|
7870
|
-
return _this;
|
7814
|
+
var TaskLoop = /*#__PURE__*/function () {
|
7815
|
+
function TaskLoop() {
|
7816
|
+
this._boundTick = void 0;
|
7817
|
+
this._tickTimer = null;
|
7818
|
+
this._tickInterval = null;
|
7819
|
+
this._tickCallCount = 0;
|
7820
|
+
this._boundTick = this.tick.bind(this);
|
7871
7821
|
}
|
7872
7822
|
var _proto = TaskLoop.prototype;
|
7873
7823
|
_proto.destroy = function destroy() {
|
@@ -7953,7 +7903,7 @@
|
|
7953
7903
|
*/;
|
7954
7904
|
_proto.doTick = function doTick() {};
|
7955
7905
|
return TaskLoop;
|
7956
|
-
}(
|
7906
|
+
}();
|
7957
7907
|
|
7958
7908
|
var FragmentState = {
|
7959
7909
|
NOT_LOADED: "NOT_LOADED",
|
@@ -8972,8 +8922,8 @@
|
|
8972
8922
|
var _frag$decryptdata;
|
8973
8923
|
var byteRangeStart = start;
|
8974
8924
|
var byteRangeEnd = end;
|
8975
|
-
if (frag.sn === 'initSegment' &&
|
8976
|
-
// MAP segment encrypted with method 'AES-128'
|
8925
|
+
if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
|
8926
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
8977
8927
|
// has the unencrypted size specified in the range.
|
8978
8928
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
8979
8929
|
var fragmentLen = end - start;
|
@@ -9006,9 +8956,6 @@
|
|
9006
8956
|
(part ? part : frag).stats.aborted = true;
|
9007
8957
|
return new LoadError(errorData);
|
9008
8958
|
}
|
9009
|
-
function isMethodFullSegmentAesCbc(method) {
|
9010
|
-
return method === 'AES-128' || method === 'AES-256';
|
9011
|
-
}
|
9012
8959
|
var LoadError = /*#__PURE__*/function (_Error) {
|
9013
8960
|
_inheritsLoose(LoadError, _Error);
|
9014
8961
|
function LoadError(data) {
|
@@ -9022,65 +8969,37 @@
|
|
9022
8969
|
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
9023
8970
|
|
9024
8971
|
var AESCrypto = /*#__PURE__*/function () {
|
9025
|
-
function AESCrypto(subtle, iv
|
8972
|
+
function AESCrypto(subtle, iv) {
|
9026
8973
|
this.subtle = void 0;
|
9027
8974
|
this.aesIV = void 0;
|
9028
|
-
this.aesMode = void 0;
|
9029
8975
|
this.subtle = subtle;
|
9030
8976
|
this.aesIV = iv;
|
9031
|
-
this.aesMode = aesMode;
|
9032
8977
|
}
|
9033
8978
|
var _proto = AESCrypto.prototype;
|
9034
8979
|
_proto.decrypt = function decrypt(data, key) {
|
9035
|
-
|
9036
|
-
|
9037
|
-
|
9038
|
-
|
9039
|
-
iv: this.aesIV
|
9040
|
-
}, key, data);
|
9041
|
-
case DecrypterAesMode.ctr:
|
9042
|
-
return this.subtle.decrypt({
|
9043
|
-
name: 'AES-CTR',
|
9044
|
-
counter: this.aesIV,
|
9045
|
-
length: 64
|
9046
|
-
},
|
9047
|
-
//64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
|
9048
|
-
key, data);
|
9049
|
-
default:
|
9050
|
-
throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
|
9051
|
-
}
|
8980
|
+
return this.subtle.decrypt({
|
8981
|
+
name: 'AES-CBC',
|
8982
|
+
iv: this.aesIV
|
8983
|
+
}, key, data);
|
9052
8984
|
};
|
9053
8985
|
return AESCrypto;
|
9054
8986
|
}();
|
9055
8987
|
|
9056
8988
|
var FastAESKey = /*#__PURE__*/function () {
|
9057
|
-
function FastAESKey(subtle, key
|
8989
|
+
function FastAESKey(subtle, key) {
|
9058
8990
|
this.subtle = void 0;
|
9059
8991
|
this.key = void 0;
|
9060
|
-
this.aesMode = void 0;
|
9061
8992
|
this.subtle = subtle;
|
9062
8993
|
this.key = key;
|
9063
|
-
this.aesMode = aesMode;
|
9064
8994
|
}
|
9065
8995
|
var _proto = FastAESKey.prototype;
|
9066
8996
|
_proto.expandKey = function expandKey() {
|
9067
|
-
var subtleAlgoName = getSubtleAlgoName(this.aesMode);
|
9068
8997
|
return this.subtle.importKey('raw', this.key, {
|
9069
|
-
name:
|
8998
|
+
name: 'AES-CBC'
|
9070
8999
|
}, false, ['encrypt', 'decrypt']);
|
9071
9000
|
};
|
9072
9001
|
return FastAESKey;
|
9073
9002
|
}();
|
9074
|
-
function getSubtleAlgoName(aesMode) {
|
9075
|
-
switch (aesMode) {
|
9076
|
-
case DecrypterAesMode.cbc:
|
9077
|
-
return 'AES-CBC';
|
9078
|
-
case DecrypterAesMode.ctr:
|
9079
|
-
return 'AES-CTR';
|
9080
|
-
default:
|
9081
|
-
throw new Error("[FastAESKey] invalid aes mode " + aesMode);
|
9082
|
-
}
|
9083
|
-
}
|
9084
9003
|
|
9085
9004
|
// PKCS7
|
9086
9005
|
function removePadding(array) {
|
@@ -9333,8 +9252,7 @@
|
|
9333
9252
|
this.currentIV = null;
|
9334
9253
|
this.currentResult = null;
|
9335
9254
|
this.useSoftware = void 0;
|
9336
|
-
this.
|
9337
|
-
this.enableSoftwareAES = config.enableSoftwareAES;
|
9255
|
+
this.useSoftware = config.enableSoftwareAES;
|
9338
9256
|
this.removePKCS7Padding = removePKCS7Padding;
|
9339
9257
|
// built in decryptor expects PKCS7 padding
|
9340
9258
|
if (removePKCS7Padding) {
|
@@ -9347,7 +9265,9 @@
|
|
9347
9265
|
/* no-op */
|
9348
9266
|
}
|
9349
9267
|
}
|
9350
|
-
|
9268
|
+
if (this.subtle === null) {
|
9269
|
+
this.useSoftware = true;
|
9270
|
+
}
|
9351
9271
|
}
|
9352
9272
|
var _proto = Decrypter.prototype;
|
9353
9273
|
_proto.destroy = function destroy() {
|
@@ -9384,11 +9304,11 @@
|
|
9384
9304
|
this.softwareDecrypter = null;
|
9385
9305
|
}
|
9386
9306
|
};
|
9387
|
-
_proto.decrypt = function decrypt(data, key, iv
|
9307
|
+
_proto.decrypt = function decrypt(data, key, iv) {
|
9388
9308
|
var _this = this;
|
9389
9309
|
if (this.useSoftware) {
|
9390
9310
|
return new Promise(function (resolve, reject) {
|
9391
|
-
_this.softwareDecrypt(new Uint8Array(data), key, iv
|
9311
|
+
_this.softwareDecrypt(new Uint8Array(data), key, iv);
|
9392
9312
|
var decryptResult = _this.flush();
|
9393
9313
|
if (decryptResult) {
|
9394
9314
|
resolve(decryptResult.buffer);
|
@@ -9397,20 +9317,16 @@
|
|
9397
9317
|
}
|
9398
9318
|
});
|
9399
9319
|
}
|
9400
|
-
return this.webCryptoDecrypt(new Uint8Array(data), key, iv
|
9320
|
+
return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
|
9401
9321
|
}
|
9402
9322
|
|
9403
9323
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
9404
9324
|
// data is handled in the flush() call
|
9405
9325
|
;
|
9406
|
-
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv
|
9326
|
+
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
|
9407
9327
|
var currentIV = this.currentIV,
|
9408
9328
|
currentResult = this.currentResult,
|
9409
9329
|
remainderData = this.remainderData;
|
9410
|
-
if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
|
9411
|
-
logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
|
9412
|
-
return null;
|
9413
|
-
}
|
9414
9330
|
this.logOnce('JS AES decrypt');
|
9415
9331
|
// The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
|
9416
9332
|
// This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
|
@@ -9443,12 +9359,12 @@
|
|
9443
9359
|
}
|
9444
9360
|
return result;
|
9445
9361
|
};
|
9446
|
-
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv
|
9362
|
+
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
|
9447
9363
|
var _this2 = this;
|
9448
9364
|
var subtle = this.subtle;
|
9449
9365
|
if (this.key !== key || !this.fastAesKey) {
|
9450
9366
|
this.key = key;
|
9451
|
-
this.fastAesKey = new FastAESKey(subtle, key
|
9367
|
+
this.fastAesKey = new FastAESKey(subtle, key);
|
9452
9368
|
}
|
9453
9369
|
return this.fastAesKey.expandKey().then(function (aesKey) {
|
9454
9370
|
// decrypt using web crypto
|
@@ -9456,25 +9372,22 @@
|
|
9456
9372
|
return Promise.reject(new Error('web crypto not initialized'));
|
9457
9373
|
}
|
9458
9374
|
_this2.logOnce('WebCrypto AES decrypt');
|
9459
|
-
var crypto = new AESCrypto(subtle, new Uint8Array(iv)
|
9375
|
+
var crypto = new AESCrypto(subtle, new Uint8Array(iv));
|
9460
9376
|
return crypto.decrypt(data.buffer, aesKey);
|
9461
9377
|
}).catch(function (err) {
|
9462
9378
|
logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
|
9463
|
-
return _this2.onWebCryptoError(data, key, iv
|
9379
|
+
return _this2.onWebCryptoError(data, key, iv);
|
9464
9380
|
});
|
9465
9381
|
};
|
9466
|
-
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv
|
9467
|
-
|
9468
|
-
|
9469
|
-
|
9470
|
-
|
9471
|
-
|
9472
|
-
|
9473
|
-
if (decryptResult) {
|
9474
|
-
return decryptResult.buffer;
|
9475
|
-
}
|
9382
|
+
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
|
9383
|
+
this.useSoftware = true;
|
9384
|
+
this.logEnabled = true;
|
9385
|
+
this.softwareDecrypt(data, key, iv);
|
9386
|
+
var decryptResult = this.flush();
|
9387
|
+
if (decryptResult) {
|
9388
|
+
return decryptResult.buffer;
|
9476
9389
|
}
|
9477
|
-
throw new Error('WebCrypto
|
9390
|
+
throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
|
9478
9391
|
};
|
9479
9392
|
_proto.getValidChunk = function getValidChunk(data) {
|
9480
9393
|
var currentChunk = data;
|
@@ -9528,7 +9441,7 @@
|
|
9528
9441
|
_inheritsLoose(BaseStreamController, _TaskLoop);
|
9529
9442
|
function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
|
9530
9443
|
var _this;
|
9531
|
-
_this = _TaskLoop.call(this
|
9444
|
+
_this = _TaskLoop.call(this) || this;
|
9532
9445
|
_this.hls = void 0;
|
9533
9446
|
_this.fragPrevious = null;
|
9534
9447
|
_this.fragCurrent = null;
|
@@ -9553,96 +9466,25 @@
|
|
9553
9466
|
_this.startFragRequested = false;
|
9554
9467
|
_this.decrypter = void 0;
|
9555
9468
|
_this.initPTS = [];
|
9556
|
-
_this.
|
9557
|
-
_this.
|
9558
|
-
_this.
|
9559
|
-
|
9560
|
-
|
9561
|
-
fragCurrent = _assertThisInitialize.fragCurrent,
|
9562
|
-
media = _assertThisInitialize.media,
|
9563
|
-
mediaBuffer = _assertThisInitialize.mediaBuffer,
|
9564
|
-
state = _assertThisInitialize.state;
|
9565
|
-
var currentTime = media ? media.currentTime : 0;
|
9566
|
-
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9567
|
-
_this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9568
|
-
if (_this.state === State.ENDED) {
|
9569
|
-
_this.resetLoadingState();
|
9570
|
-
} else if (fragCurrent) {
|
9571
|
-
// Seeking while frag load is in progress
|
9572
|
-
var tolerance = config.maxFragLookUpTolerance;
|
9573
|
-
var fragStartOffset = fragCurrent.start - tolerance;
|
9574
|
-
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9575
|
-
// if seeking out of buffered range or into new one
|
9576
|
-
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9577
|
-
var pastFragment = currentTime > fragEndOffset;
|
9578
|
-
// if the seek position is outside the current fragment range
|
9579
|
-
if (currentTime < fragStartOffset || pastFragment) {
|
9580
|
-
if (pastFragment && fragCurrent.loader) {
|
9581
|
-
_this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9582
|
-
fragCurrent.abortRequests();
|
9583
|
-
_this.resetLoadingState();
|
9584
|
-
}
|
9585
|
-
_this.fragPrevious = null;
|
9586
|
-
}
|
9587
|
-
}
|
9588
|
-
}
|
9589
|
-
if (media) {
|
9590
|
-
// Remove gap fragments
|
9591
|
-
_this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
|
9592
|
-
_this.lastCurrentTime = currentTime;
|
9593
|
-
if (!_this.loadingParts) {
|
9594
|
-
var bufferEnd = Math.max(bufferInfo.end, currentTime);
|
9595
|
-
var shouldLoadParts = _this.shouldLoadParts(_this.getLevelDetails(), bufferEnd);
|
9596
|
-
if (shouldLoadParts) {
|
9597
|
-
_this.log("LL-Part loading ON after seeking to " + currentTime.toFixed(2) + " with buffer @" + bufferEnd.toFixed(2));
|
9598
|
-
_this.loadingParts = shouldLoadParts;
|
9599
|
-
}
|
9600
|
-
}
|
9601
|
-
}
|
9602
|
-
|
9603
|
-
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9604
|
-
if (!_this.loadedmetadata && !bufferInfo.len) {
|
9605
|
-
_this.nextLoadPosition = _this.startPosition = currentTime;
|
9606
|
-
}
|
9607
|
-
|
9608
|
-
// Async tick to speed up processing
|
9609
|
-
_this.tickImmediate();
|
9610
|
-
};
|
9611
|
-
_this.onMediaEnded = function () {
|
9612
|
-
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9613
|
-
_this.startPosition = _this.lastCurrentTime = 0;
|
9614
|
-
if (_this.playlistType === PlaylistLevelType.MAIN) {
|
9615
|
-
_this.hls.trigger(Events.MEDIA_ENDED, {
|
9616
|
-
stalled: false
|
9617
|
-
});
|
9618
|
-
}
|
9619
|
-
};
|
9469
|
+
_this.onvseeking = null;
|
9470
|
+
_this.onvended = null;
|
9471
|
+
_this.logPrefix = '';
|
9472
|
+
_this.log = void 0;
|
9473
|
+
_this.warn = void 0;
|
9620
9474
|
_this.playlistType = playlistType;
|
9475
|
+
_this.logPrefix = logPrefix;
|
9476
|
+
_this.log = logger.log.bind(logger, logPrefix + ":");
|
9477
|
+
_this.warn = logger.warn.bind(logger, logPrefix + ":");
|
9621
9478
|
_this.hls = hls;
|
9622
9479
|
_this.fragmentLoader = new FragmentLoader(hls.config);
|
9623
9480
|
_this.keyLoader = keyLoader;
|
9624
9481
|
_this.fragmentTracker = fragmentTracker;
|
9625
9482
|
_this.config = hls.config;
|
9626
9483
|
_this.decrypter = new Decrypter(hls.config);
|
9484
|
+
hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
|
9627
9485
|
return _this;
|
9628
9486
|
}
|
9629
9487
|
var _proto = BaseStreamController.prototype;
|
9630
|
-
_proto.registerListeners = function registerListeners() {
|
9631
|
-
var hls = this.hls;
|
9632
|
-
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9633
|
-
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9634
|
-
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9635
|
-
hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9636
|
-
hls.on(Events.ERROR, this.onError, this);
|
9637
|
-
};
|
9638
|
-
_proto.unregisterListeners = function unregisterListeners() {
|
9639
|
-
var hls = this.hls;
|
9640
|
-
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
9641
|
-
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
9642
|
-
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
9643
|
-
hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
|
9644
|
-
hls.off(Events.ERROR, this.onError, this);
|
9645
|
-
};
|
9646
9488
|
_proto.doTick = function doTick() {
|
9647
9489
|
this.onTickEnd();
|
9648
9490
|
};
|
@@ -9666,12 +9508,6 @@
|
|
9666
9508
|
this.clearNextTick();
|
9667
9509
|
this.state = State.STOPPED;
|
9668
9510
|
};
|
9669
|
-
_proto.pauseBuffering = function pauseBuffering() {
|
9670
|
-
this.buffering = false;
|
9671
|
-
};
|
9672
|
-
_proto.resumeBuffering = function resumeBuffering() {
|
9673
|
-
this.buffering = true;
|
9674
|
-
};
|
9675
9511
|
_proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
|
9676
9512
|
// If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
|
9677
9513
|
// of nothing loading/loaded return false
|
@@ -9702,8 +9538,10 @@
|
|
9702
9538
|
};
|
9703
9539
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
9704
9540
|
var media = this.media = this.mediaBuffer = data.media;
|
9705
|
-
|
9706
|
-
|
9541
|
+
this.onvseeking = this.onMediaSeeking.bind(this);
|
9542
|
+
this.onvended = this.onMediaEnded.bind(this);
|
9543
|
+
media.addEventListener('seeking', this.onvseeking);
|
9544
|
+
media.addEventListener('ended', this.onvended);
|
9707
9545
|
var config = this.config;
|
9708
9546
|
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
|
9709
9547
|
this.startLoad(config.startPosition);
|
@@ -9717,9 +9555,10 @@
|
|
9717
9555
|
}
|
9718
9556
|
|
9719
9557
|
// remove video listeners
|
9720
|
-
if (media) {
|
9721
|
-
media.removeEventListener('seeking', this.
|
9722
|
-
media.removeEventListener('ended', this.
|
9558
|
+
if (media && this.onvseeking && this.onvended) {
|
9559
|
+
media.removeEventListener('seeking', this.onvseeking);
|
9560
|
+
media.removeEventListener('ended', this.onvended);
|
9561
|
+
this.onvseeking = this.onvended = null;
|
9723
9562
|
}
|
9724
9563
|
if (this.keyLoader) {
|
9725
9564
|
this.keyLoader.detach();
|
@@ -9729,8 +9568,54 @@
|
|
9729
9568
|
this.fragmentTracker.removeAllFragments();
|
9730
9569
|
this.stopLoad();
|
9731
9570
|
};
|
9732
|
-
_proto.
|
9733
|
-
|
9571
|
+
_proto.onMediaSeeking = function onMediaSeeking() {
|
9572
|
+
var config = this.config,
|
9573
|
+
fragCurrent = this.fragCurrent,
|
9574
|
+
media = this.media,
|
9575
|
+
mediaBuffer = this.mediaBuffer,
|
9576
|
+
state = this.state;
|
9577
|
+
var currentTime = media ? media.currentTime : 0;
|
9578
|
+
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9579
|
+
this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9580
|
+
if (this.state === State.ENDED) {
|
9581
|
+
this.resetLoadingState();
|
9582
|
+
} else if (fragCurrent) {
|
9583
|
+
// Seeking while frag load is in progress
|
9584
|
+
var tolerance = config.maxFragLookUpTolerance;
|
9585
|
+
var fragStartOffset = fragCurrent.start - tolerance;
|
9586
|
+
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9587
|
+
// if seeking out of buffered range or into new one
|
9588
|
+
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9589
|
+
var pastFragment = currentTime > fragEndOffset;
|
9590
|
+
// if the seek position is outside the current fragment range
|
9591
|
+
if (currentTime < fragStartOffset || pastFragment) {
|
9592
|
+
if (pastFragment && fragCurrent.loader) {
|
9593
|
+
this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9594
|
+
fragCurrent.abortRequests();
|
9595
|
+
this.resetLoadingState();
|
9596
|
+
}
|
9597
|
+
this.fragPrevious = null;
|
9598
|
+
}
|
9599
|
+
}
|
9600
|
+
}
|
9601
|
+
if (media) {
|
9602
|
+
// Remove gap fragments
|
9603
|
+
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
9604
|
+
this.lastCurrentTime = currentTime;
|
9605
|
+
}
|
9606
|
+
|
9607
|
+
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9608
|
+
if (!this.loadedmetadata && !bufferInfo.len) {
|
9609
|
+
this.nextLoadPosition = this.startPosition = currentTime;
|
9610
|
+
}
|
9611
|
+
|
9612
|
+
// Async tick to speed up processing
|
9613
|
+
this.tickImmediate();
|
9614
|
+
};
|
9615
|
+
_proto.onMediaEnded = function onMediaEnded() {
|
9616
|
+
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9617
|
+
this.startPosition = this.lastCurrentTime = 0;
|
9618
|
+
};
|
9734
9619
|
_proto.onManifestLoaded = function onManifestLoaded(event, data) {
|
9735
9620
|
this.startTimeOffset = data.startTimeOffset;
|
9736
9621
|
this.initPTS = [];
|
@@ -9740,7 +9625,7 @@
|
|
9740
9625
|
this.stopLoad();
|
9741
9626
|
_TaskLoop.prototype.onHandlerDestroying.call(this);
|
9742
9627
|
// @ts-ignore
|
9743
|
-
this.hls =
|
9628
|
+
this.hls = null;
|
9744
9629
|
};
|
9745
9630
|
_proto.onHandlerDestroyed = function onHandlerDestroyed() {
|
9746
9631
|
this.state = State.STOPPED;
|
@@ -9870,10 +9755,10 @@
|
|
9870
9755
|
var decryptData = frag.decryptdata;
|
9871
9756
|
|
9872
9757
|
// check to see if the payload needs to be decrypted
|
9873
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
9758
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
9874
9759
|
var startTime = self.performance.now();
|
9875
9760
|
// decrypt init segment data
|
9876
|
-
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
9761
|
+
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
9877
9762
|
hls.trigger(Events.ERROR, {
|
9878
9763
|
type: ErrorTypes.MEDIA_ERROR,
|
9879
9764
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -9986,7 +9871,7 @@
|
|
9986
9871
|
}
|
9987
9872
|
var keyLoadingPromise = null;
|
9988
9873
|
if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
|
9989
|
-
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.
|
9874
|
+
this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level);
|
9990
9875
|
this.state = State.KEY_LOADING;
|
9991
9876
|
this.fragCurrent = frag;
|
9992
9877
|
keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
|
@@ -10007,16 +9892,8 @@
|
|
10007
9892
|
} else if (!frag.encrypted && details.encryptedFragments.length) {
|
10008
9893
|
this.keyLoader.loadClear(frag, details.encryptedFragments);
|
10009
9894
|
}
|
10010
|
-
var fragPrevious = this.fragPrevious;
|
10011
|
-
if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
|
10012
|
-
var shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
|
10013
|
-
if (shouldLoadParts !== this.loadingParts) {
|
10014
|
-
this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " loading sn " + (fragPrevious == null ? void 0 : fragPrevious.sn) + "->" + frag.sn);
|
10015
|
-
this.loadingParts = shouldLoadParts;
|
10016
|
-
}
|
10017
|
-
}
|
10018
9895
|
targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
|
10019
|
-
if (this.
|
9896
|
+
if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {
|
10020
9897
|
var partList = details.partList;
|
10021
9898
|
if (partList && progressCallback) {
|
10022
9899
|
if (targetBufferTime > frag.end && details.fragmentHint) {
|
@@ -10025,7 +9902,7 @@
|
|
10025
9902
|
var partIndex = this.getNextPart(partList, frag, targetBufferTime);
|
10026
9903
|
if (partIndex > -1) {
|
10027
9904
|
var part = partList[partIndex];
|
10028
|
-
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.
|
9905
|
+
this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
|
10029
9906
|
this.nextLoadPosition = part.start + part.duration;
|
10030
9907
|
this.state = State.FRAG_LOADING;
|
10031
9908
|
var _result;
|
@@ -10058,14 +9935,7 @@
|
|
10058
9935
|
}
|
10059
9936
|
}
|
10060
9937
|
}
|
10061
|
-
|
10062
|
-
this.log("LL-Part loading OFF after next part miss @" + targetBufferTime.toFixed(2));
|
10063
|
-
this.loadingParts = false;
|
10064
|
-
} else if (!frag.url) {
|
10065
|
-
// Selected fragment hint for part but not loading parts
|
10066
|
-
return Promise.resolve(null);
|
10067
|
-
}
|
10068
|
-
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)));
|
9938
|
+
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)));
|
10069
9939
|
// Don't update nextLoadPosition for fragments which are not buffered
|
10070
9940
|
if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
|
10071
9941
|
this.nextLoadPosition = frag.start + frag.duration;
|
@@ -10167,36 +10037,8 @@
|
|
10167
10037
|
if (part) {
|
10168
10038
|
part.stats.parsing.end = now;
|
10169
10039
|
}
|
10170
|
-
// See if part loading should be disabled/enabled based on buffer and playback position.
|
10171
|
-
if (frag.sn !== 'initSegment') {
|
10172
|
-
var levelDetails = this.getLevelDetails();
|
10173
|
-
var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
|
10174
|
-
var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
|
10175
|
-
if (shouldLoadParts !== this.loadingParts) {
|
10176
|
-
this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
|
10177
|
-
this.loadingParts = shouldLoadParts;
|
10178
|
-
}
|
10179
|
-
}
|
10180
10040
|
this.updateLevelTiming(frag, part, level, chunkMeta.partial);
|
10181
10041
|
};
|
10182
|
-
_proto.shouldLoadParts = function shouldLoadParts(details, bufferEnd) {
|
10183
|
-
if (this.config.lowLatencyMode) {
|
10184
|
-
if (!details) {
|
10185
|
-
return this.loadingParts;
|
10186
|
-
}
|
10187
|
-
if (details != null && details.partList) {
|
10188
|
-
var _details$fragmentHint;
|
10189
|
-
// Buffer must be ahead of first part + duration of parts after last segment
|
10190
|
-
// and playback must be at or past segment adjacent to part list
|
10191
|
-
var firstPart = details.partList[0];
|
10192
|
-
var safePartStart = firstPart.end + (((_details$fragmentHint = details.fragmentHint) == null ? void 0 : _details$fragmentHint.duration) || 0);
|
10193
|
-
if (bufferEnd >= safePartStart && this.lastCurrentTime > firstPart.start - firstPart.fragment.duration) {
|
10194
|
-
return true;
|
10195
|
-
}
|
10196
|
-
}
|
10197
|
-
}
|
10198
|
-
return false;
|
10199
|
-
};
|
10200
10042
|
_proto.getCurrentContext = function getCurrentContext(chunkMeta) {
|
10201
10043
|
var levels = this.levels,
|
10202
10044
|
fragCurrent = this.fragCurrent;
|
@@ -10331,8 +10173,7 @@
|
|
10331
10173
|
// find fragment index, contiguous with end of buffer position
|
10332
10174
|
var config = this.config;
|
10333
10175
|
var start = fragments[0].start;
|
10334
|
-
var
|
10335
|
-
var frag = null;
|
10176
|
+
var frag;
|
10336
10177
|
if (levelDetails.live) {
|
10337
10178
|
var initialLiveManifestSize = config.initialLiveManifestSize;
|
10338
10179
|
if (fragLen < initialLiveManifestSize) {
|
@@ -10344,10 +10185,6 @@
|
|
10344
10185
|
// Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that
|
10345
10186
|
// we get the fragment matching that start time
|
10346
10187
|
if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1 || pos < start) {
|
10347
|
-
if (canLoadParts && !this.loadingParts) {
|
10348
|
-
this.log("LL-Part loading ON for initial live fragment");
|
10349
|
-
this.loadingParts = true;
|
10350
|
-
}
|
10351
10188
|
frag = this.getInitialLiveFragment(levelDetails, fragments);
|
10352
10189
|
this.startPosition = this.nextLoadPosition = frag ? this.hls.liveSyncPosition || frag.start : pos;
|
10353
10190
|
}
|
@@ -10358,7 +10195,7 @@
|
|
10358
10195
|
|
10359
10196
|
// If we haven't run into any special cases already, just load the fragment most closely matching the requested position
|
10360
10197
|
if (!frag) {
|
10361
|
-
var end =
|
10198
|
+
var end = config.lowLatencyMode ? levelDetails.partEnd : levelDetails.fragmentEnd;
|
10362
10199
|
frag = this.getFragmentAtPosition(pos, end, levelDetails);
|
10363
10200
|
}
|
10364
10201
|
return this.mapToInitFragWhenRequired(frag);
|
@@ -10472,7 +10309,7 @@
|
|
10472
10309
|
var fragmentHint = levelDetails.fragmentHint;
|
10473
10310
|
var tolerance = config.maxFragLookUpTolerance;
|
10474
10311
|
var partList = levelDetails.partList;
|
10475
|
-
var loadingParts = !!(
|
10312
|
+
var loadingParts = !!(config.lowLatencyMode && partList != null && partList.length && fragmentHint);
|
10476
10313
|
if (loadingParts && fragmentHint && !this.bitrateTest) {
|
10477
10314
|
// Include incomplete fragment with parts at end
|
10478
10315
|
fragments = fragments.concat(fragmentHint);
|
@@ -10659,7 +10496,7 @@
|
|
10659
10496
|
errorAction.resolved = true;
|
10660
10497
|
}
|
10661
10498
|
} else {
|
10662
|
-
|
10499
|
+
logger.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
|
10663
10500
|
return;
|
10664
10501
|
}
|
10665
10502
|
} else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
|
@@ -11059,7 +10896,6 @@
|
|
11059
10896
|
*/
|
11060
10897
|
function getAudioConfig(observer, data, offset, audioCodec) {
|
11061
10898
|
var adtsObjectType;
|
11062
|
-
var originalAdtsObjectType;
|
11063
10899
|
var adtsExtensionSamplingIndex;
|
11064
10900
|
var adtsChannelConfig;
|
11065
10901
|
var config;
|
@@ -11067,7 +10903,7 @@
|
|
11067
10903
|
var manifestCodec = audioCodec;
|
11068
10904
|
var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
|
11069
10905
|
// byte 2
|
11070
|
-
adtsObjectType =
|
10906
|
+
adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
11071
10907
|
var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
|
11072
10908
|
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
|
11073
10909
|
var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
|
@@ -11084,8 +10920,8 @@
|
|
11084
10920
|
// byte 3
|
11085
10921
|
adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
|
11086
10922
|
logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
|
11087
|
-
//
|
11088
|
-
if (/firefox
|
10923
|
+
// firefox: freq less than 24kHz = AAC SBR (HE-AAC)
|
10924
|
+
if (/firefox/i.test(userAgent)) {
|
11089
10925
|
if (adtsSamplingIndex >= 6) {
|
11090
10926
|
adtsObjectType = 5;
|
11091
10927
|
config = new Array(4);
|
@@ -11179,7 +11015,6 @@
|
|
11179
11015
|
samplerate: adtsSamplingRates[adtsSamplingIndex],
|
11180
11016
|
channelCount: adtsChannelConfig,
|
11181
11017
|
codec: 'mp4a.40.' + adtsObjectType,
|
11182
|
-
parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
|
11183
11018
|
manifestCodec: manifestCodec
|
11184
11019
|
};
|
11185
11020
|
}
|
@@ -11234,8 +11069,7 @@
|
|
11234
11069
|
track.channelCount = config.channelCount;
|
11235
11070
|
track.codec = config.codec;
|
11236
11071
|
track.manifestCodec = config.manifestCodec;
|
11237
|
-
track.
|
11238
|
-
logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11072
|
+
logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11239
11073
|
}
|
11240
11074
|
}
|
11241
11075
|
function getFrameDuration(samplerate) {
|
@@ -11833,110 +11667,6 @@
|
|
11833
11667
|
logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
|
11834
11668
|
}
|
11835
11669
|
};
|
11836
|
-
_proto.parseNALu = function parseNALu(track, array) {
|
11837
|
-
var len = array.byteLength;
|
11838
|
-
var state = track.naluState || 0;
|
11839
|
-
var lastState = state;
|
11840
|
-
var units = [];
|
11841
|
-
var i = 0;
|
11842
|
-
var value;
|
11843
|
-
var overflow;
|
11844
|
-
var unitType;
|
11845
|
-
var lastUnitStart = -1;
|
11846
|
-
var lastUnitType = 0;
|
11847
|
-
// logger.log('PES:' + Hex.hexDump(array));
|
11848
|
-
|
11849
|
-
if (state === -1) {
|
11850
|
-
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
11851
|
-
lastUnitStart = 0;
|
11852
|
-
// NALu type is value read from offset 0
|
11853
|
-
lastUnitType = this.getNALuType(array, 0);
|
11854
|
-
state = 0;
|
11855
|
-
i = 1;
|
11856
|
-
}
|
11857
|
-
while (i < len) {
|
11858
|
-
value = array[i++];
|
11859
|
-
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
11860
|
-
if (!state) {
|
11861
|
-
state = value ? 0 : 1;
|
11862
|
-
continue;
|
11863
|
-
}
|
11864
|
-
if (state === 1) {
|
11865
|
-
state = value ? 0 : 2;
|
11866
|
-
continue;
|
11867
|
-
}
|
11868
|
-
// here we have state either equal to 2 or 3
|
11869
|
-
if (!value) {
|
11870
|
-
state = 3;
|
11871
|
-
} else if (value === 1) {
|
11872
|
-
overflow = i - state - 1;
|
11873
|
-
if (lastUnitStart >= 0) {
|
11874
|
-
var unit = {
|
11875
|
-
data: array.subarray(lastUnitStart, overflow),
|
11876
|
-
type: lastUnitType
|
11877
|
-
};
|
11878
|
-
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
|
11879
|
-
units.push(unit);
|
11880
|
-
} else {
|
11881
|
-
// lastUnitStart is undefined => this is the first start code found in this PES packet
|
11882
|
-
// first check if start code delimiter is overlapping between 2 PES packets,
|
11883
|
-
// ie it started in last packet (lastState not zero)
|
11884
|
-
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
11885
|
-
var lastUnit = this.getLastNalUnit(track.samples);
|
11886
|
-
if (lastUnit) {
|
11887
|
-
if (lastState && i <= 4 - lastState) {
|
11888
|
-
// start delimiter overlapping between PES packets
|
11889
|
-
// strip start delimiter bytes from the end of last NAL unit
|
11890
|
-
// check if lastUnit had a state different from zero
|
11891
|
-
if (lastUnit.state) {
|
11892
|
-
// strip last bytes
|
11893
|
-
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
|
11894
|
-
}
|
11895
|
-
}
|
11896
|
-
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
|
11897
|
-
|
11898
|
-
if (overflow > 0) {
|
11899
|
-
// logger.log('first NALU found with overflow:' + overflow);
|
11900
|
-
lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
|
11901
|
-
lastUnit.state = 0;
|
11902
|
-
}
|
11903
|
-
}
|
11904
|
-
}
|
11905
|
-
// check if we can read unit type
|
11906
|
-
if (i < len) {
|
11907
|
-
unitType = this.getNALuType(array, i);
|
11908
|
-
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
11909
|
-
lastUnitStart = i;
|
11910
|
-
lastUnitType = unitType;
|
11911
|
-
state = 0;
|
11912
|
-
} else {
|
11913
|
-
// not enough byte to read unit type. let's read it on next PES parsing
|
11914
|
-
state = -1;
|
11915
|
-
}
|
11916
|
-
} else {
|
11917
|
-
state = 0;
|
11918
|
-
}
|
11919
|
-
}
|
11920
|
-
if (lastUnitStart >= 0 && state >= 0) {
|
11921
|
-
var _unit = {
|
11922
|
-
data: array.subarray(lastUnitStart, len),
|
11923
|
-
type: lastUnitType,
|
11924
|
-
state: state
|
11925
|
-
};
|
11926
|
-
units.push(_unit);
|
11927
|
-
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
11928
|
-
}
|
11929
|
-
// no NALu found
|
11930
|
-
if (units.length === 0) {
|
11931
|
-
// append pes.data to previous NAL unit
|
11932
|
-
var _lastUnit = this.getLastNalUnit(track.samples);
|
11933
|
-
if (_lastUnit) {
|
11934
|
-
_lastUnit.data = appendUint8Array(_lastUnit.data, array);
|
11935
|
-
}
|
11936
|
-
}
|
11937
|
-
track.naluState = state;
|
11938
|
-
return units;
|
11939
|
-
};
|
11940
11670
|
return BaseVideoParser;
|
11941
11671
|
}();
|
11942
11672
|
|
@@ -12091,236 +11821,78 @@
|
|
12091
11821
|
;
|
12092
11822
|
_proto.readUInt = function readUInt() {
|
12093
11823
|
return this.readBits(32);
|
12094
|
-
};
|
12095
|
-
return ExpGolomb;
|
12096
|
-
}();
|
12097
|
-
|
12098
|
-
var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
|
12099
|
-
_inheritsLoose(AvcVideoParser, _BaseVideoParser);
|
12100
|
-
function AvcVideoParser() {
|
12101
|
-
return _BaseVideoParser.apply(this, arguments) || this;
|
12102
11824
|
}
|
12103
|
-
var _proto = AvcVideoParser.prototype;
|
12104
|
-
_proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
|
12105
|
-
var _this = this;
|
12106
|
-
var units = this.parseNALu(track, pes.data);
|
12107
|
-
var VideoSample = this.VideoSample;
|
12108
|
-
var push;
|
12109
|
-
var spsfound = false;
|
12110
|
-
// free pes.data to save up some memory
|
12111
|
-
pes.data = null;
|
12112
11825
|
|
12113
|
-
|
12114
|
-
|
12115
|
-
|
12116
|
-
|
12117
|
-
|
11826
|
+
/**
|
11827
|
+
* Advance the ExpGolomb decoder past a scaling list. The scaling
|
11828
|
+
* list is optionally transmitted as part of a sequence parameter
|
11829
|
+
* set and is not relevant to transmuxing.
|
11830
|
+
* @param count the number of entries in this scaling list
|
11831
|
+
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
11832
|
+
*/;
|
11833
|
+
_proto.skipScalingList = function skipScalingList(count) {
|
11834
|
+
var lastScale = 8;
|
11835
|
+
var nextScale = 8;
|
11836
|
+
var deltaScale;
|
11837
|
+
for (var j = 0; j < count; j++) {
|
11838
|
+
if (nextScale !== 0) {
|
11839
|
+
deltaScale = this.readEG();
|
11840
|
+
nextScale = (lastScale + deltaScale + 256) % 256;
|
11841
|
+
}
|
11842
|
+
lastScale = nextScale === 0 ? lastScale : nextScale;
|
12118
11843
|
}
|
12119
|
-
|
12120
|
-
|
12121
|
-
|
12122
|
-
|
12123
|
-
|
12124
|
-
|
12125
|
-
|
12126
|
-
|
12127
|
-
|
12128
|
-
|
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
|
-
if (
|
12166
|
-
|
12167
|
-
|
12168
|
-
|
12169
|
-
|
12170
|
-
|
12171
|
-
// SEI
|
12172
|
-
case 6:
|
12173
|
-
{
|
12174
|
-
push = true;
|
12175
|
-
parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
|
12176
|
-
break;
|
12177
|
-
// SPS
|
12178
|
-
}
|
12179
|
-
case 7:
|
12180
|
-
{
|
12181
|
-
var _track$pixelRatio, _track$pixelRatio2;
|
12182
|
-
push = true;
|
12183
|
-
spsfound = true;
|
12184
|
-
var sps = unit.data;
|
12185
|
-
var config = _this.readSPS(sps);
|
12186
|
-
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]) {
|
12187
|
-
track.width = config.width;
|
12188
|
-
track.height = config.height;
|
12189
|
-
track.pixelRatio = config.pixelRatio;
|
12190
|
-
track.sps = [sps];
|
12191
|
-
track.duration = duration;
|
12192
|
-
var codecarray = sps.subarray(1, 4);
|
12193
|
-
var codecstring = 'avc1.';
|
12194
|
-
for (var i = 0; i < 3; i++) {
|
12195
|
-
var h = codecarray[i].toString(16);
|
12196
|
-
if (h.length < 2) {
|
12197
|
-
h = '0' + h;
|
12198
|
-
}
|
12199
|
-
codecstring += h;
|
12200
|
-
}
|
12201
|
-
track.codec = codecstring;
|
12202
|
-
}
|
12203
|
-
break;
|
12204
|
-
}
|
12205
|
-
// PPS
|
12206
|
-
case 8:
|
12207
|
-
push = true;
|
12208
|
-
track.pps = [unit.data];
|
12209
|
-
break;
|
12210
|
-
// AUD
|
12211
|
-
case 9:
|
12212
|
-
push = true;
|
12213
|
-
track.audFound = true;
|
12214
|
-
if (VideoSample) {
|
12215
|
-
_this.pushAccessUnit(VideoSample, track);
|
12216
|
-
}
|
12217
|
-
VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
|
12218
|
-
break;
|
12219
|
-
// Filler Data
|
12220
|
-
case 12:
|
12221
|
-
push = true;
|
12222
|
-
break;
|
12223
|
-
default:
|
12224
|
-
push = false;
|
12225
|
-
if (VideoSample) {
|
12226
|
-
VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
|
12227
|
-
}
|
12228
|
-
break;
|
12229
|
-
}
|
12230
|
-
if (VideoSample && push) {
|
12231
|
-
var _units = VideoSample.units;
|
12232
|
-
_units.push(unit);
|
12233
|
-
}
|
12234
|
-
});
|
12235
|
-
// if last PES packet, push samples
|
12236
|
-
if (last && VideoSample) {
|
12237
|
-
this.pushAccessUnit(VideoSample, track);
|
12238
|
-
this.VideoSample = null;
|
12239
|
-
}
|
12240
|
-
};
|
12241
|
-
_proto.getNALuType = function getNALuType(data, offset) {
|
12242
|
-
return data[offset] & 0x1f;
|
12243
|
-
};
|
12244
|
-
_proto.readSliceType = function readSliceType(data) {
|
12245
|
-
var eg = new ExpGolomb(data);
|
12246
|
-
// skip NALu type
|
12247
|
-
eg.readUByte();
|
12248
|
-
// discard first_mb_in_slice
|
12249
|
-
eg.readUEG();
|
12250
|
-
// return slice_type
|
12251
|
-
return eg.readUEG();
|
12252
|
-
}
|
12253
|
-
|
12254
|
-
/**
|
12255
|
-
* The scaling list is optionally transmitted as part of a sequence parameter
|
12256
|
-
* set and is not relevant to transmuxing.
|
12257
|
-
* @param count the number of entries in this scaling list
|
12258
|
-
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
12259
|
-
*/;
|
12260
|
-
_proto.skipScalingList = function skipScalingList(count, reader) {
|
12261
|
-
var lastScale = 8;
|
12262
|
-
var nextScale = 8;
|
12263
|
-
var deltaScale;
|
12264
|
-
for (var j = 0; j < count; j++) {
|
12265
|
-
if (nextScale !== 0) {
|
12266
|
-
deltaScale = reader.readEG();
|
12267
|
-
nextScale = (lastScale + deltaScale + 256) % 256;
|
12268
|
-
}
|
12269
|
-
lastScale = nextScale === 0 ? lastScale : nextScale;
|
12270
|
-
}
|
12271
|
-
}
|
12272
|
-
|
12273
|
-
/**
|
12274
|
-
* Read a sequence parameter set and return some interesting video
|
12275
|
-
* properties. A sequence parameter set is the H264 metadata that
|
12276
|
-
* describes the properties of upcoming video frames.
|
12277
|
-
* @returns an object with configuration parsed from the
|
12278
|
-
* sequence parameter set, including the dimensions of the
|
12279
|
-
* associated video frames.
|
12280
|
-
*/;
|
12281
|
-
_proto.readSPS = function readSPS(sps) {
|
12282
|
-
var eg = new ExpGolomb(sps);
|
12283
|
-
var frameCropLeftOffset = 0;
|
12284
|
-
var frameCropRightOffset = 0;
|
12285
|
-
var frameCropTopOffset = 0;
|
12286
|
-
var frameCropBottomOffset = 0;
|
12287
|
-
var numRefFramesInPicOrderCntCycle;
|
12288
|
-
var scalingListCount;
|
12289
|
-
var i;
|
12290
|
-
var readUByte = eg.readUByte.bind(eg);
|
12291
|
-
var readBits = eg.readBits.bind(eg);
|
12292
|
-
var readUEG = eg.readUEG.bind(eg);
|
12293
|
-
var readBoolean = eg.readBoolean.bind(eg);
|
12294
|
-
var skipBits = eg.skipBits.bind(eg);
|
12295
|
-
var skipEG = eg.skipEG.bind(eg);
|
12296
|
-
var skipUEG = eg.skipUEG.bind(eg);
|
12297
|
-
var skipScalingList = this.skipScalingList.bind(this);
|
12298
|
-
readUByte();
|
12299
|
-
var profileIdc = readUByte(); // profile_idc
|
12300
|
-
readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
|
12301
|
-
skipBits(3); // reserved_zero_3bits u(3),
|
12302
|
-
readUByte(); // level_idc u(8)
|
12303
|
-
skipUEG(); // seq_parameter_set_id
|
12304
|
-
// some profiles have more optional data we don't need
|
12305
|
-
if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
|
12306
|
-
var chromaFormatIdc = readUEG();
|
12307
|
-
if (chromaFormatIdc === 3) {
|
12308
|
-
skipBits(1);
|
12309
|
-
} // separate_colour_plane_flag
|
12310
|
-
|
12311
|
-
skipUEG(); // bit_depth_luma_minus8
|
12312
|
-
skipUEG(); // bit_depth_chroma_minus8
|
12313
|
-
skipBits(1); // qpprime_y_zero_transform_bypass_flag
|
12314
|
-
if (readBoolean()) {
|
12315
|
-
// seq_scaling_matrix_present_flag
|
12316
|
-
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
|
12317
|
-
for (i = 0; i < scalingListCount; i++) {
|
12318
|
-
if (readBoolean()) {
|
12319
|
-
// seq_scaling_list_present_flag[ i ]
|
12320
|
-
if (i < 6) {
|
12321
|
-
skipScalingList(16, eg);
|
12322
|
-
} else {
|
12323
|
-
skipScalingList(64, eg);
|
11844
|
+
}
|
11845
|
+
|
11846
|
+
/**
|
11847
|
+
* Read a sequence parameter set and return some interesting video
|
11848
|
+
* properties. A sequence parameter set is the H264 metadata that
|
11849
|
+
* describes the properties of upcoming video frames.
|
11850
|
+
* @returns an object with configuration parsed from the
|
11851
|
+
* sequence parameter set, including the dimensions of the
|
11852
|
+
* associated video frames.
|
11853
|
+
*/;
|
11854
|
+
_proto.readSPS = function readSPS() {
|
11855
|
+
var frameCropLeftOffset = 0;
|
11856
|
+
var frameCropRightOffset = 0;
|
11857
|
+
var frameCropTopOffset = 0;
|
11858
|
+
var frameCropBottomOffset = 0;
|
11859
|
+
var numRefFramesInPicOrderCntCycle;
|
11860
|
+
var scalingListCount;
|
11861
|
+
var i;
|
11862
|
+
var readUByte = this.readUByte.bind(this);
|
11863
|
+
var readBits = this.readBits.bind(this);
|
11864
|
+
var readUEG = this.readUEG.bind(this);
|
11865
|
+
var readBoolean = this.readBoolean.bind(this);
|
11866
|
+
var skipBits = this.skipBits.bind(this);
|
11867
|
+
var skipEG = this.skipEG.bind(this);
|
11868
|
+
var skipUEG = this.skipUEG.bind(this);
|
11869
|
+
var skipScalingList = this.skipScalingList.bind(this);
|
11870
|
+
readUByte();
|
11871
|
+
var profileIdc = readUByte(); // profile_idc
|
11872
|
+
readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
|
11873
|
+
skipBits(3); // reserved_zero_3bits u(3),
|
11874
|
+
readUByte(); // level_idc u(8)
|
11875
|
+
skipUEG(); // seq_parameter_set_id
|
11876
|
+
// some profiles have more optional data we don't need
|
11877
|
+
if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
|
11878
|
+
var chromaFormatIdc = readUEG();
|
11879
|
+
if (chromaFormatIdc === 3) {
|
11880
|
+
skipBits(1);
|
11881
|
+
} // separate_colour_plane_flag
|
11882
|
+
|
11883
|
+
skipUEG(); // bit_depth_luma_minus8
|
11884
|
+
skipUEG(); // bit_depth_chroma_minus8
|
11885
|
+
skipBits(1); // qpprime_y_zero_transform_bypass_flag
|
11886
|
+
if (readBoolean()) {
|
11887
|
+
// seq_scaling_matrix_present_flag
|
11888
|
+
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
|
11889
|
+
for (i = 0; i < scalingListCount; i++) {
|
11890
|
+
if (readBoolean()) {
|
11891
|
+
// seq_scaling_list_present_flag[ i ]
|
11892
|
+
if (i < 6) {
|
11893
|
+
skipScalingList(16);
|
11894
|
+
} else {
|
11895
|
+
skipScalingList(64);
|
12324
11896
|
}
|
12325
11897
|
}
|
12326
11898
|
}
|
@@ -12425,24 +11997,26 @@
|
|
12425
11997
|
pixelRatio: pixelRatio
|
12426
11998
|
};
|
12427
11999
|
};
|
12428
|
-
|
12429
|
-
|
12000
|
+
_proto.readSliceType = function readSliceType() {
|
12001
|
+
// skip NALu type
|
12002
|
+
this.readUByte();
|
12003
|
+
// discard first_mb_in_slice
|
12004
|
+
this.readUEG();
|
12005
|
+
// return slice_type
|
12006
|
+
return this.readUEG();
|
12007
|
+
};
|
12008
|
+
return ExpGolomb;
|
12009
|
+
}();
|
12430
12010
|
|
12431
|
-
var
|
12432
|
-
_inheritsLoose(
|
12433
|
-
function
|
12434
|
-
|
12435
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
12436
|
-
args[_key] = arguments[_key];
|
12437
|
-
}
|
12438
|
-
_this = _BaseVideoParser.call.apply(_BaseVideoParser, [this].concat(args)) || this;
|
12439
|
-
_this.initVPS = null;
|
12440
|
-
return _this;
|
12011
|
+
var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
|
12012
|
+
_inheritsLoose(AvcVideoParser, _BaseVideoParser);
|
12013
|
+
function AvcVideoParser() {
|
12014
|
+
return _BaseVideoParser.apply(this, arguments) || this;
|
12441
12015
|
}
|
12442
|
-
var _proto =
|
12443
|
-
_proto.
|
12444
|
-
var
|
12445
|
-
var units = this.
|
12016
|
+
var _proto = AvcVideoParser.prototype;
|
12017
|
+
_proto.parseAVCPES = function parseAVCPES(track, textTrack, pes, last, duration) {
|
12018
|
+
var _this = this;
|
12019
|
+
var units = this.parseAVCNALu(track, pes.data);
|
12446
12020
|
var VideoSample = this.VideoSample;
|
12447
12021
|
var push;
|
12448
12022
|
var spsfound = false;
|
@@ -12458,143 +12032,112 @@
|
|
12458
12032
|
units.forEach(function (unit) {
|
12459
12033
|
var _VideoSample2;
|
12460
12034
|
switch (unit.type) {
|
12461
|
-
//
|
12462
|
-
case 0:
|
12035
|
+
// NDR
|
12463
12036
|
case 1:
|
12464
|
-
|
12465
|
-
|
12466
|
-
|
12467
|
-
|
12468
|
-
|
12469
|
-
|
12470
|
-
|
12471
|
-
|
12472
|
-
|
12473
|
-
|
12474
|
-
|
12475
|
-
|
12476
|
-
|
12477
|
-
|
12478
|
-
|
12479
|
-
|
12480
|
-
case 16:
|
12481
|
-
case 17:
|
12482
|
-
case 18:
|
12483
|
-
case 21:
|
12484
|
-
push = true;
|
12485
|
-
if (spsfound) {
|
12486
|
-
var _VideoSample;
|
12487
|
-
// handle PES not starting with AUD
|
12488
|
-
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12489
|
-
if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
|
12490
|
-
_this2.pushAccessUnit(VideoSample, track);
|
12491
|
-
VideoSample = _this2.VideoSample = null;
|
12037
|
+
{
|
12038
|
+
var iskey = false;
|
12039
|
+
push = true;
|
12040
|
+
var data = unit.data;
|
12041
|
+
// only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
|
12042
|
+
if (spsfound && data.length > 4) {
|
12043
|
+
// retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
|
12044
|
+
var sliceType = new ExpGolomb(data).readSliceType();
|
12045
|
+
// 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
|
12046
|
+
// SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
|
12047
|
+
// An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
|
12048
|
+
// I slice: A slice that is not an SI slice that is decoded using intra prediction only.
|
12049
|
+
// if (sliceType === 2 || sliceType === 7) {
|
12050
|
+
if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
|
12051
|
+
iskey = true;
|
12052
|
+
}
|
12492
12053
|
}
|
12054
|
+
if (iskey) {
|
12055
|
+
var _VideoSample;
|
12056
|
+
// if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
|
12057
|
+
if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
|
12058
|
+
_this.pushAccessUnit(VideoSample, track);
|
12059
|
+
VideoSample = _this.VideoSample = null;
|
12060
|
+
}
|
12061
|
+
}
|
12062
|
+
if (!VideoSample) {
|
12063
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
|
12064
|
+
}
|
12065
|
+
VideoSample.frame = true;
|
12066
|
+
VideoSample.key = iskey;
|
12067
|
+
break;
|
12068
|
+
// IDR
|
12493
12069
|
}
|
12494
|
-
|
12495
|
-
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12496
|
-
}
|
12497
|
-
VideoSample.key = true;
|
12498
|
-
VideoSample.frame = true;
|
12499
|
-
break;
|
12500
|
-
|
12501
|
-
// IDR
|
12502
|
-
case 19:
|
12503
|
-
case 20:
|
12070
|
+
case 5:
|
12504
12071
|
push = true;
|
12505
12072
|
// handle PES not starting with AUD
|
12506
12073
|
// if we have frame data already, that cannot belong to the same frame, so force a push
|
12507
12074
|
if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
|
12508
|
-
|
12509
|
-
VideoSample =
|
12075
|
+
_this.pushAccessUnit(VideoSample, track);
|
12076
|
+
VideoSample = _this.VideoSample = null;
|
12510
12077
|
}
|
12511
12078
|
if (!VideoSample) {
|
12512
|
-
VideoSample =
|
12079
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
|
12513
12080
|
}
|
12514
12081
|
VideoSample.key = true;
|
12515
12082
|
VideoSample.frame = true;
|
12516
12083
|
break;
|
12517
|
-
|
12518
12084
|
// SEI
|
12519
|
-
case
|
12520
|
-
|
12521
|
-
|
12522
|
-
|
12523
|
-
|
12524
|
-
|
12525
|
-
|
12526
|
-
// VPS
|
12527
|
-
case 32:
|
12528
|
-
push = true;
|
12529
|
-
if (!track.vps) {
|
12530
|
-
var config = _this2.readVPS(unit.data);
|
12531
|
-
track.params = _objectSpread2({}, config);
|
12532
|
-
_this2.initVPS = unit.data;
|
12085
|
+
case 6:
|
12086
|
+
{
|
12087
|
+
push = true;
|
12088
|
+
parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
|
12089
|
+
break;
|
12090
|
+
// SPS
|
12533
12091
|
}
|
12534
|
-
|
12535
|
-
|
12536
|
-
|
12537
|
-
|
12538
|
-
|
12539
|
-
|
12540
|
-
|
12541
|
-
|
12542
|
-
if (track.
|
12543
|
-
|
12544
|
-
track.
|
12545
|
-
|
12546
|
-
|
12547
|
-
var _config = _this2.readSPS(unit.data);
|
12548
|
-
track.width = _config.width;
|
12549
|
-
track.height = _config.height;
|
12550
|
-
track.pixelRatio = _config.pixelRatio;
|
12092
|
+
case 7:
|
12093
|
+
{
|
12094
|
+
var _track$pixelRatio, _track$pixelRatio2;
|
12095
|
+
push = true;
|
12096
|
+
spsfound = true;
|
12097
|
+
var sps = unit.data;
|
12098
|
+
var expGolombDecoder = new ExpGolomb(sps);
|
12099
|
+
var config = expGolombDecoder.readSPS();
|
12100
|
+
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]) {
|
12101
|
+
track.width = config.width;
|
12102
|
+
track.height = config.height;
|
12103
|
+
track.pixelRatio = config.pixelRatio;
|
12104
|
+
track.sps = [sps];
|
12551
12105
|
track.duration = duration;
|
12552
|
-
|
12553
|
-
|
12554
|
-
for (var
|
12555
|
-
|
12106
|
+
var codecarray = sps.subarray(1, 4);
|
12107
|
+
var codecstring = 'avc1.';
|
12108
|
+
for (var i = 0; i < 3; i++) {
|
12109
|
+
var h = codecarray[i].toString(16);
|
12110
|
+
if (h.length < 2) {
|
12111
|
+
h = '0' + h;
|
12112
|
+
}
|
12113
|
+
codecstring += h;
|
12556
12114
|
}
|
12115
|
+
track.codec = codecstring;
|
12557
12116
|
}
|
12558
|
-
|
12559
|
-
track.sps.push(unit.data);
|
12560
|
-
}
|
12561
|
-
}
|
12562
|
-
if (!VideoSample) {
|
12563
|
-
VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
|
12117
|
+
break;
|
12564
12118
|
}
|
12565
|
-
VideoSample.key = true;
|
12566
|
-
break;
|
12567
|
-
|
12568
12119
|
// PPS
|
12569
|
-
case
|
12120
|
+
case 8:
|
12570
12121
|
push = true;
|
12571
|
-
|
12572
|
-
if (!track.pps) {
|
12573
|
-
track.pps = [];
|
12574
|
-
var _config2 = _this2.readPPS(unit.data);
|
12575
|
-
for (var _prop in _config2) {
|
12576
|
-
track.params[_prop] = _config2[_prop];
|
12577
|
-
}
|
12578
|
-
}
|
12579
|
-
if (_this2.initVPS !== null || track.pps.length === 0) {
|
12580
|
-
track.pps.push(unit.data);
|
12581
|
-
}
|
12582
|
-
}
|
12122
|
+
track.pps = [unit.data];
|
12583
12123
|
break;
|
12584
|
-
|
12585
|
-
|
12586
|
-
case 35:
|
12124
|
+
// AUD
|
12125
|
+
case 9:
|
12587
12126
|
push = true;
|
12588
12127
|
track.audFound = true;
|
12589
12128
|
if (VideoSample) {
|
12590
|
-
|
12129
|
+
_this.pushAccessUnit(VideoSample, track);
|
12591
12130
|
}
|
12592
|
-
VideoSample =
|
12131
|
+
VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
|
12132
|
+
break;
|
12133
|
+
// Filler Data
|
12134
|
+
case 12:
|
12135
|
+
push = true;
|
12593
12136
|
break;
|
12594
12137
|
default:
|
12595
12138
|
push = false;
|
12596
12139
|
if (VideoSample) {
|
12597
|
-
VideoSample.debug += 'unknown
|
12140
|
+
VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
|
12598
12141
|
}
|
12599
12142
|
break;
|
12600
12143
|
}
|
@@ -12609,425 +12152,111 @@
|
|
12609
12152
|
this.VideoSample = null;
|
12610
12153
|
}
|
12611
12154
|
};
|
12612
|
-
_proto.
|
12613
|
-
|
12614
|
-
|
12615
|
-
|
12616
|
-
var
|
12617
|
-
var
|
12618
|
-
|
12619
|
-
|
12620
|
-
|
12621
|
-
|
12622
|
-
|
12623
|
-
|
12624
|
-
}
|
12625
|
-
dst[dstIdx] = arr[i];
|
12626
|
-
dstIdx++;
|
12627
|
-
}
|
12628
|
-
return new Uint8Array(dst.buffer, 0, dstIdx);
|
12629
|
-
};
|
12630
|
-
_proto.readVPS = function readVPS(vps) {
|
12631
|
-
var eg = new ExpGolomb(vps);
|
12632
|
-
// remove header
|
12633
|
-
eg.readUByte();
|
12634
|
-
eg.readUByte();
|
12635
|
-
eg.readBits(4); // video_parameter_set_id
|
12636
|
-
eg.skipBits(2);
|
12637
|
-
eg.readBits(6); // max_layers_minus1
|
12638
|
-
var max_sub_layers_minus1 = eg.readBits(3);
|
12639
|
-
var temporal_id_nesting_flag = eg.readBoolean();
|
12640
|
-
// ...vui fps can be here, but empty fps value is not critical for metadata
|
12155
|
+
_proto.parseAVCNALu = function parseAVCNALu(track, array) {
|
12156
|
+
var len = array.byteLength;
|
12157
|
+
var state = track.naluState || 0;
|
12158
|
+
var lastState = state;
|
12159
|
+
var units = [];
|
12160
|
+
var i = 0;
|
12161
|
+
var value;
|
12162
|
+
var overflow;
|
12163
|
+
var unitType;
|
12164
|
+
var lastUnitStart = -1;
|
12165
|
+
var lastUnitType = 0;
|
12166
|
+
// logger.log('PES:' + Hex.hexDump(array));
|
12641
12167
|
|
12642
|
-
|
12643
|
-
|
12644
|
-
|
12645
|
-
|
12646
|
-
|
12647
|
-
|
12648
|
-
|
12649
|
-
eg.readUByte();
|
12650
|
-
eg.readUByte();
|
12651
|
-
eg.readBits(4); //video_parameter_set_id
|
12652
|
-
var max_sub_layers_minus1 = eg.readBits(3);
|
12653
|
-
eg.readBoolean(); // temporal_id_nesting_flag
|
12654
|
-
|
12655
|
-
// profile_tier_level
|
12656
|
-
var general_profile_space = eg.readBits(2);
|
12657
|
-
var general_tier_flag = eg.readBoolean();
|
12658
|
-
var general_profile_idc = eg.readBits(5);
|
12659
|
-
var general_profile_compatibility_flags_1 = eg.readUByte();
|
12660
|
-
var general_profile_compatibility_flags_2 = eg.readUByte();
|
12661
|
-
var general_profile_compatibility_flags_3 = eg.readUByte();
|
12662
|
-
var general_profile_compatibility_flags_4 = eg.readUByte();
|
12663
|
-
var general_constraint_indicator_flags_1 = eg.readUByte();
|
12664
|
-
var general_constraint_indicator_flags_2 = eg.readUByte();
|
12665
|
-
var general_constraint_indicator_flags_3 = eg.readUByte();
|
12666
|
-
var general_constraint_indicator_flags_4 = eg.readUByte();
|
12667
|
-
var general_constraint_indicator_flags_5 = eg.readUByte();
|
12668
|
-
var general_constraint_indicator_flags_6 = eg.readUByte();
|
12669
|
-
var general_level_idc = eg.readUByte();
|
12670
|
-
var sub_layer_profile_present_flags = [];
|
12671
|
-
var sub_layer_level_present_flags = [];
|
12672
|
-
for (var i = 0; i < max_sub_layers_minus1; i++) {
|
12673
|
-
sub_layer_profile_present_flags.push(eg.readBoolean());
|
12674
|
-
sub_layer_level_present_flags.push(eg.readBoolean());
|
12675
|
-
}
|
12676
|
-
if (max_sub_layers_minus1 > 0) {
|
12677
|
-
for (var _i = max_sub_layers_minus1; _i < 8; _i++) {
|
12678
|
-
eg.readBits(2);
|
12679
|
-
}
|
12680
|
-
}
|
12681
|
-
for (var _i2 = 0; _i2 < max_sub_layers_minus1; _i2++) {
|
12682
|
-
if (sub_layer_profile_present_flags[_i2]) {
|
12683
|
-
eg.readUByte(); // sub_layer_profile_space, sub_layer_tier_flag, sub_layer_profile_idc
|
12684
|
-
eg.readUByte();
|
12685
|
-
eg.readUByte();
|
12686
|
-
eg.readUByte();
|
12687
|
-
eg.readUByte(); // sub_layer_profile_compatibility_flag
|
12688
|
-
eg.readUByte();
|
12689
|
-
eg.readUByte();
|
12690
|
-
eg.readUByte();
|
12691
|
-
eg.readUByte();
|
12692
|
-
eg.readUByte();
|
12693
|
-
eg.readUByte();
|
12694
|
-
}
|
12695
|
-
if (sub_layer_level_present_flags[_i2]) {
|
12696
|
-
eg.readUByte();
|
12697
|
-
}
|
12698
|
-
}
|
12699
|
-
eg.readUEG(); // seq_parameter_set_id
|
12700
|
-
var chroma_format_idc = eg.readUEG();
|
12701
|
-
if (chroma_format_idc == 3) {
|
12702
|
-
eg.skipBits(1); //separate_colour_plane_flag
|
12703
|
-
}
|
12704
|
-
var pic_width_in_luma_samples = eg.readUEG();
|
12705
|
-
var pic_height_in_luma_samples = eg.readUEG();
|
12706
|
-
var conformance_window_flag = eg.readBoolean();
|
12707
|
-
var pic_left_offset = 0,
|
12708
|
-
pic_right_offset = 0,
|
12709
|
-
pic_top_offset = 0,
|
12710
|
-
pic_bottom_offset = 0;
|
12711
|
-
if (conformance_window_flag) {
|
12712
|
-
pic_left_offset += eg.readUEG();
|
12713
|
-
pic_right_offset += eg.readUEG();
|
12714
|
-
pic_top_offset += eg.readUEG();
|
12715
|
-
pic_bottom_offset += eg.readUEG();
|
12716
|
-
}
|
12717
|
-
var bit_depth_luma_minus8 = eg.readUEG();
|
12718
|
-
var bit_depth_chroma_minus8 = eg.readUEG();
|
12719
|
-
var log2_max_pic_order_cnt_lsb_minus4 = eg.readUEG();
|
12720
|
-
var sub_layer_ordering_info_present_flag = eg.readBoolean();
|
12721
|
-
for (var _i3 = sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; _i3 <= max_sub_layers_minus1; _i3++) {
|
12722
|
-
eg.skipUEG(); // max_dec_pic_buffering_minus1[i]
|
12723
|
-
eg.skipUEG(); // max_num_reorder_pics[i]
|
12724
|
-
eg.skipUEG(); // max_latency_increase_plus1[i]
|
12725
|
-
}
|
12726
|
-
eg.skipUEG(); // log2_min_luma_coding_block_size_minus3
|
12727
|
-
eg.skipUEG(); // log2_diff_max_min_luma_coding_block_size
|
12728
|
-
eg.skipUEG(); // log2_min_transform_block_size_minus2
|
12729
|
-
eg.skipUEG(); // log2_diff_max_min_transform_block_size
|
12730
|
-
eg.skipUEG(); // max_transform_hierarchy_depth_inter
|
12731
|
-
eg.skipUEG(); // max_transform_hierarchy_depth_intra
|
12732
|
-
var scaling_list_enabled_flag = eg.readBoolean();
|
12733
|
-
if (scaling_list_enabled_flag) {
|
12734
|
-
var sps_scaling_list_data_present_flag = eg.readBoolean();
|
12735
|
-
if (sps_scaling_list_data_present_flag) {
|
12736
|
-
for (var sizeId = 0; sizeId < 4; sizeId++) {
|
12737
|
-
for (var matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
|
12738
|
-
var scaling_list_pred_mode_flag = eg.readBoolean();
|
12739
|
-
if (!scaling_list_pred_mode_flag) {
|
12740
|
-
eg.readUEG(); // scaling_list_pred_matrix_id_delta
|
12741
|
-
} else {
|
12742
|
-
var coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
|
12743
|
-
if (sizeId > 1) {
|
12744
|
-
eg.readEG();
|
12745
|
-
}
|
12746
|
-
for (var _i4 = 0; _i4 < coefNum; _i4++) {
|
12747
|
-
eg.readEG();
|
12748
|
-
}
|
12749
|
-
}
|
12750
|
-
}
|
12751
|
-
}
|
12752
|
-
}
|
12168
|
+
if (state === -1) {
|
12169
|
+
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
12170
|
+
lastUnitStart = 0;
|
12171
|
+
// NALu type is value read from offset 0
|
12172
|
+
lastUnitType = array[0] & 0x1f;
|
12173
|
+
state = 0;
|
12174
|
+
i = 1;
|
12753
12175
|
}
|
12754
|
-
|
12755
|
-
|
12756
|
-
|
12757
|
-
|
12758
|
-
|
12759
|
-
|
12760
|
-
|
12761
|
-
|
12762
|
-
|
12763
|
-
|
12764
|
-
|
12765
|
-
|
12766
|
-
|
12767
|
-
|
12768
|
-
|
12769
|
-
|
12770
|
-
|
12771
|
-
|
12772
|
-
|
12773
|
-
|
12774
|
-
|
12775
|
-
|
12776
|
-
|
12777
|
-
|
12778
|
-
|
12779
|
-
|
12780
|
-
|
12781
|
-
|
12782
|
-
|
12783
|
-
if (
|
12784
|
-
|
12785
|
-
|
12786
|
-
|
12787
|
-
|
12788
|
-
|
12789
|
-
|
12790
|
-
|
12791
|
-
num_delta_pocs = num_negative_pics + num_positive_pics;
|
12792
|
-
for (var _j = 0; _j < num_negative_pics; _j++) {
|
12793
|
-
eg.readUEG();
|
12794
|
-
eg.readBoolean();
|
12795
|
-
}
|
12796
|
-
for (var _j2 = 0; _j2 < num_positive_pics; _j2++) {
|
12797
|
-
eg.readUEG();
|
12798
|
-
eg.readBoolean();
|
12799
|
-
}
|
12800
|
-
}
|
12801
|
-
}
|
12802
|
-
var long_term_ref_pics_present_flag = eg.readBoolean();
|
12803
|
-
if (long_term_ref_pics_present_flag) {
|
12804
|
-
var num_long_term_ref_pics_sps = eg.readUEG();
|
12805
|
-
for (var _i6 = 0; _i6 < num_long_term_ref_pics_sps; _i6++) {
|
12806
|
-
for (var _j3 = 0; _j3 < log2_max_pic_order_cnt_lsb_minus4 + 4; _j3++) {
|
12807
|
-
eg.readBits(1);
|
12808
|
-
}
|
12809
|
-
eg.readBits(1);
|
12810
|
-
}
|
12811
|
-
}
|
12812
|
-
var min_spatial_segmentation_idc = 0;
|
12813
|
-
var sar_width = 1,
|
12814
|
-
sar_height = 1;
|
12815
|
-
var fps_fixed = true,
|
12816
|
-
fps_den = 1,
|
12817
|
-
fps_num = 0;
|
12818
|
-
eg.readBoolean(); // sps_temporal_mvp_enabled_flag
|
12819
|
-
eg.readBoolean(); // strong_intra_smoothing_enabled_flag
|
12820
|
-
var default_display_window_flag = false;
|
12821
|
-
var vui_parameters_present_flag = eg.readBoolean();
|
12822
|
-
if (vui_parameters_present_flag) {
|
12823
|
-
var aspect_ratio_info_present_flag = eg.readBoolean();
|
12824
|
-
if (aspect_ratio_info_present_flag) {
|
12825
|
-
var aspect_ratio_idc = eg.readUByte();
|
12826
|
-
var sar_width_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
|
12827
|
-
var sar_height_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
|
12828
|
-
if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
|
12829
|
-
sar_width = sar_width_table[aspect_ratio_idc - 1];
|
12830
|
-
sar_height = sar_height_table[aspect_ratio_idc - 1];
|
12831
|
-
} else if (aspect_ratio_idc === 255) {
|
12832
|
-
sar_width = eg.readBits(16);
|
12833
|
-
sar_height = eg.readBits(16);
|
12834
|
-
}
|
12835
|
-
}
|
12836
|
-
var overscan_info_present_flag = eg.readBoolean();
|
12837
|
-
if (overscan_info_present_flag) {
|
12838
|
-
eg.readBoolean();
|
12839
|
-
}
|
12840
|
-
var video_signal_type_present_flag = eg.readBoolean();
|
12841
|
-
if (video_signal_type_present_flag) {
|
12842
|
-
eg.readBits(3);
|
12843
|
-
eg.readBoolean();
|
12844
|
-
var colour_description_present_flag = eg.readBoolean();
|
12845
|
-
if (colour_description_present_flag) {
|
12846
|
-
eg.readUByte();
|
12847
|
-
eg.readUByte();
|
12848
|
-
eg.readUByte();
|
12849
|
-
}
|
12850
|
-
}
|
12851
|
-
var chroma_loc_info_present_flag = eg.readBoolean();
|
12852
|
-
if (chroma_loc_info_present_flag) {
|
12853
|
-
eg.readUEG();
|
12854
|
-
eg.readUEG();
|
12855
|
-
}
|
12856
|
-
eg.readBoolean(); // neutral_chroma_indication_flag
|
12857
|
-
eg.readBoolean(); // field_seq_flag
|
12858
|
-
eg.readBoolean(); // frame_field_info_present_flag
|
12859
|
-
default_display_window_flag = eg.readBoolean();
|
12860
|
-
if (default_display_window_flag) {
|
12861
|
-
pic_left_offset += eg.readUEG();
|
12862
|
-
pic_right_offset += eg.readUEG();
|
12863
|
-
pic_top_offset += eg.readUEG();
|
12864
|
-
pic_bottom_offset += eg.readUEG();
|
12865
|
-
}
|
12866
|
-
var vui_timing_info_present_flag = eg.readBoolean();
|
12867
|
-
if (vui_timing_info_present_flag) {
|
12868
|
-
fps_den = eg.readBits(32);
|
12869
|
-
fps_num = eg.readBits(32);
|
12870
|
-
var vui_poc_proportional_to_timing_flag = eg.readBoolean();
|
12871
|
-
if (vui_poc_proportional_to_timing_flag) {
|
12872
|
-
eg.readUEG();
|
12873
|
-
}
|
12874
|
-
var vui_hrd_parameters_present_flag = eg.readBoolean();
|
12875
|
-
if (vui_hrd_parameters_present_flag) {
|
12876
|
-
//const commonInfPresentFlag = true;
|
12877
|
-
//if (commonInfPresentFlag) {
|
12878
|
-
var nal_hrd_parameters_present_flag = eg.readBoolean();
|
12879
|
-
var vcl_hrd_parameters_present_flag = eg.readBoolean();
|
12880
|
-
var sub_pic_hrd_params_present_flag = false;
|
12881
|
-
if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
|
12882
|
-
sub_pic_hrd_params_present_flag = eg.readBoolean();
|
12883
|
-
if (sub_pic_hrd_params_present_flag) {
|
12884
|
-
eg.readUByte();
|
12885
|
-
eg.readBits(5);
|
12886
|
-
eg.readBoolean();
|
12887
|
-
eg.readBits(5);
|
12888
|
-
}
|
12889
|
-
eg.readBits(4); // bit_rate_scale
|
12890
|
-
eg.readBits(4); // cpb_size_scale
|
12891
|
-
if (sub_pic_hrd_params_present_flag) {
|
12892
|
-
eg.readBits(4);
|
12893
|
-
}
|
12894
|
-
eg.readBits(5);
|
12895
|
-
eg.readBits(5);
|
12896
|
-
eg.readBits(5);
|
12897
|
-
}
|
12898
|
-
//}
|
12899
|
-
for (var _i7 = 0; _i7 <= max_sub_layers_minus1; _i7++) {
|
12900
|
-
fps_fixed = eg.readBoolean(); // fixed_pic_rate_general_flag
|
12901
|
-
var fixed_pic_rate_within_cvs_flag = fps_fixed || eg.readBoolean();
|
12902
|
-
var low_delay_hrd_flag = false;
|
12903
|
-
if (fixed_pic_rate_within_cvs_flag) {
|
12904
|
-
eg.readEG();
|
12905
|
-
} else {
|
12906
|
-
low_delay_hrd_flag = eg.readBoolean();
|
12907
|
-
}
|
12908
|
-
var cpb_cnt = low_delay_hrd_flag ? 1 : eg.readUEG() + 1;
|
12909
|
-
if (nal_hrd_parameters_present_flag) {
|
12910
|
-
for (var _j4 = 0; _j4 < cpb_cnt; _j4++) {
|
12911
|
-
eg.readUEG();
|
12912
|
-
eg.readUEG();
|
12913
|
-
if (sub_pic_hrd_params_present_flag) {
|
12914
|
-
eg.readUEG();
|
12915
|
-
eg.readUEG();
|
12916
|
-
}
|
12917
|
-
eg.skipBits(1);
|
12176
|
+
while (i < len) {
|
12177
|
+
value = array[i++];
|
12178
|
+
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
12179
|
+
if (!state) {
|
12180
|
+
state = value ? 0 : 1;
|
12181
|
+
continue;
|
12182
|
+
}
|
12183
|
+
if (state === 1) {
|
12184
|
+
state = value ? 0 : 2;
|
12185
|
+
continue;
|
12186
|
+
}
|
12187
|
+
// here we have state either equal to 2 or 3
|
12188
|
+
if (!value) {
|
12189
|
+
state = 3;
|
12190
|
+
} else if (value === 1) {
|
12191
|
+
overflow = i - state - 1;
|
12192
|
+
if (lastUnitStart >= 0) {
|
12193
|
+
var unit = {
|
12194
|
+
data: array.subarray(lastUnitStart, overflow),
|
12195
|
+
type: lastUnitType
|
12196
|
+
};
|
12197
|
+
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
|
12198
|
+
units.push(unit);
|
12199
|
+
} else {
|
12200
|
+
// lastUnitStart is undefined => this is the first start code found in this PES packet
|
12201
|
+
// first check if start code delimiter is overlapping between 2 PES packets,
|
12202
|
+
// ie it started in last packet (lastState not zero)
|
12203
|
+
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
12204
|
+
var lastUnit = this.getLastNalUnit(track.samples);
|
12205
|
+
if (lastUnit) {
|
12206
|
+
if (lastState && i <= 4 - lastState) {
|
12207
|
+
// start delimiter overlapping between PES packets
|
12208
|
+
// strip start delimiter bytes from the end of last NAL unit
|
12209
|
+
// check if lastUnit had a state different from zero
|
12210
|
+
if (lastUnit.state) {
|
12211
|
+
// strip last bytes
|
12212
|
+
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
|
12918
12213
|
}
|
12919
12214
|
}
|
12920
|
-
|
12921
|
-
|
12922
|
-
|
12923
|
-
|
12924
|
-
|
12925
|
-
|
12926
|
-
eg.readUEG();
|
12927
|
-
}
|
12928
|
-
eg.skipBits(1);
|
12929
|
-
}
|
12215
|
+
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
|
12216
|
+
|
12217
|
+
if (overflow > 0) {
|
12218
|
+
// logger.log('first NALU found with overflow:' + overflow);
|
12219
|
+
lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
|
12220
|
+
lastUnit.state = 0;
|
12930
12221
|
}
|
12931
12222
|
}
|
12932
12223
|
}
|
12933
|
-
|
12934
|
-
|
12935
|
-
|
12936
|
-
|
12937
|
-
|
12938
|
-
|
12939
|
-
|
12940
|
-
|
12941
|
-
|
12942
|
-
|
12943
|
-
height = pic_height_in_luma_samples;
|
12944
|
-
if (conformance_window_flag || default_display_window_flag) {
|
12945
|
-
var chroma_scale_w = 1,
|
12946
|
-
chroma_scale_h = 1;
|
12947
|
-
if (chroma_format_idc === 1) {
|
12948
|
-
// YUV 420
|
12949
|
-
chroma_scale_w = chroma_scale_h = 2;
|
12950
|
-
} else if (chroma_format_idc == 2) {
|
12951
|
-
// YUV 422
|
12952
|
-
chroma_scale_w = 2;
|
12953
|
-
}
|
12954
|
-
width = pic_width_in_luma_samples - chroma_scale_w * pic_right_offset - chroma_scale_w * pic_left_offset;
|
12955
|
-
height = pic_height_in_luma_samples - chroma_scale_h * pic_bottom_offset - chroma_scale_h * pic_top_offset;
|
12956
|
-
}
|
12957
|
-
var profile_space_string = general_profile_space ? ['A', 'B', 'C'][general_profile_space] : '';
|
12958
|
-
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;
|
12959
|
-
var profile_compatibility_rev = 0;
|
12960
|
-
for (var _i8 = 0; _i8 < 32; _i8++) {
|
12961
|
-
profile_compatibility_rev = (profile_compatibility_rev | (profile_compatibility_buf >> _i8 & 1) << 31 - _i8) >>> 0; // reverse bit position (and cast as UInt32)
|
12962
|
-
}
|
12963
|
-
var profile_compatibility_flags_string = profile_compatibility_rev.toString(16);
|
12964
|
-
if (general_profile_idc === 1 && profile_compatibility_flags_string === '2') {
|
12965
|
-
profile_compatibility_flags_string = '6';
|
12966
|
-
}
|
12967
|
-
var tier_flag_string = general_tier_flag ? 'H' : 'L';
|
12968
|
-
return {
|
12969
|
-
codecString: "hvc1." + profile_space_string + general_profile_idc + "." + profile_compatibility_flags_string + "." + tier_flag_string + general_level_idc + ".B0",
|
12970
|
-
params: {
|
12971
|
-
general_tier_flag: general_tier_flag,
|
12972
|
-
general_profile_idc: general_profile_idc,
|
12973
|
-
general_profile_space: general_profile_space,
|
12974
|
-
general_profile_compatibility_flags: [general_profile_compatibility_flags_1, general_profile_compatibility_flags_2, general_profile_compatibility_flags_3, general_profile_compatibility_flags_4],
|
12975
|
-
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],
|
12976
|
-
general_level_idc: general_level_idc,
|
12977
|
-
bit_depth: bit_depth_luma_minus8 + 8,
|
12978
|
-
bit_depth_luma_minus8: bit_depth_luma_minus8,
|
12979
|
-
bit_depth_chroma_minus8: bit_depth_chroma_minus8,
|
12980
|
-
min_spatial_segmentation_idc: min_spatial_segmentation_idc,
|
12981
|
-
chroma_format_idc: chroma_format_idc,
|
12982
|
-
frame_rate: {
|
12983
|
-
fixed: fps_fixed,
|
12984
|
-
fps: fps_num / fps_den
|
12224
|
+
// check if we can read unit type
|
12225
|
+
if (i < len) {
|
12226
|
+
unitType = array[i] & 0x1f;
|
12227
|
+
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
12228
|
+
lastUnitStart = i;
|
12229
|
+
lastUnitType = unitType;
|
12230
|
+
state = 0;
|
12231
|
+
} else {
|
12232
|
+
// not enough byte to read unit type. let's read it on next PES parsing
|
12233
|
+
state = -1;
|
12985
12234
|
}
|
12986
|
-
}
|
12987
|
-
|
12988
|
-
|
12989
|
-
pixelRatio: [sar_width, sar_height]
|
12990
|
-
};
|
12991
|
-
};
|
12992
|
-
_proto.readPPS = function readPPS(pps) {
|
12993
|
-
var eg = new ExpGolomb(this.ebsp2rbsp(pps));
|
12994
|
-
eg.readUByte();
|
12995
|
-
eg.readUByte();
|
12996
|
-
eg.skipUEG(); // pic_parameter_set_id
|
12997
|
-
eg.skipUEG(); // seq_parameter_set_id
|
12998
|
-
eg.skipBits(2); // dependent_slice_segments_enabled_flag, output_flag_present_flag
|
12999
|
-
eg.skipBits(3); // num_extra_slice_header_bits
|
13000
|
-
eg.skipBits(2); // sign_data_hiding_enabled_flag, cabac_init_present_flag
|
13001
|
-
eg.skipUEG();
|
13002
|
-
eg.skipUEG();
|
13003
|
-
eg.skipEG(); // init_qp_minus26
|
13004
|
-
eg.skipBits(2); // constrained_intra_pred_flag, transform_skip_enabled_flag
|
13005
|
-
var cu_qp_delta_enabled_flag = eg.readBoolean();
|
13006
|
-
if (cu_qp_delta_enabled_flag) {
|
13007
|
-
eg.skipUEG();
|
13008
|
-
}
|
13009
|
-
eg.skipEG(); // cb_qp_offset
|
13010
|
-
eg.skipEG(); // cr_qp_offset
|
13011
|
-
eg.skipBits(4); // pps_slice_chroma_qp_offsets_present_flag, weighted_pred_flag, weighted_bipred_flag, transquant_bypass_enabled_flag
|
13012
|
-
var tiles_enabled_flag = eg.readBoolean();
|
13013
|
-
var entropy_coding_sync_enabled_flag = eg.readBoolean();
|
13014
|
-
var parallelismType = 1; // slice-based parallel decoding
|
13015
|
-
if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) {
|
13016
|
-
parallelismType = 0; // mixed-type parallel decoding
|
13017
|
-
} else if (entropy_coding_sync_enabled_flag) {
|
13018
|
-
parallelismType = 3; // wavefront-based parallel decoding
|
13019
|
-
} else if (tiles_enabled_flag) {
|
13020
|
-
parallelismType = 2; // tile-based parallel decoding
|
12235
|
+
} else {
|
12236
|
+
state = 0;
|
12237
|
+
}
|
13021
12238
|
}
|
13022
|
-
|
13023
|
-
|
13024
|
-
|
13025
|
-
|
13026
|
-
|
13027
|
-
|
13028
|
-
|
12239
|
+
if (lastUnitStart >= 0 && state >= 0) {
|
12240
|
+
var _unit = {
|
12241
|
+
data: array.subarray(lastUnitStart, len),
|
12242
|
+
type: lastUnitType,
|
12243
|
+
state: state
|
12244
|
+
};
|
12245
|
+
units.push(_unit);
|
12246
|
+
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
12247
|
+
}
|
12248
|
+
// no NALu found
|
12249
|
+
if (units.length === 0) {
|
12250
|
+
// append pes.data to previous NAL unit
|
12251
|
+
var _lastUnit = this.getLastNalUnit(track.samples);
|
12252
|
+
if (_lastUnit) {
|
12253
|
+
_lastUnit.data = appendUint8Array(_lastUnit.data, array);
|
12254
|
+
}
|
12255
|
+
}
|
12256
|
+
track.naluState = state;
|
12257
|
+
return units;
|
13029
12258
|
};
|
13030
|
-
return
|
12259
|
+
return AvcVideoParser;
|
13031
12260
|
}(BaseVideoParser);
|
13032
12261
|
|
13033
12262
|
/**
|
@@ -13045,7 +12274,7 @@
|
|
13045
12274
|
}
|
13046
12275
|
var _proto = SampleAesDecrypter.prototype;
|
13047
12276
|
_proto.decryptBuffer = function decryptBuffer(encryptedData) {
|
13048
|
-
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer
|
12277
|
+
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
|
13049
12278
|
}
|
13050
12279
|
|
13051
12280
|
// AAC - encrypt all full 16 bytes blocks starting from offset 16
|
@@ -13164,7 +12393,7 @@
|
|
13164
12393
|
this.observer = observer;
|
13165
12394
|
this.config = config;
|
13166
12395
|
this.typeSupported = typeSupported;
|
13167
|
-
this.videoParser =
|
12396
|
+
this.videoParser = new AvcVideoParser();
|
13168
12397
|
}
|
13169
12398
|
TSDemuxer.probe = function probe(data) {
|
13170
12399
|
var syncOffset = TSDemuxer.syncOffset(data);
|
@@ -13334,21 +12563,7 @@
|
|
13334
12563
|
case videoPid:
|
13335
12564
|
if (stt) {
|
13336
12565
|
if (videoData && (pes = parsePES(videoData))) {
|
13337
|
-
|
13338
|
-
switch (videoTrack.segmentCodec) {
|
13339
|
-
case 'avc':
|
13340
|
-
this.videoParser = new AvcVideoParser();
|
13341
|
-
break;
|
13342
|
-
case 'hevc':
|
13343
|
-
{
|
13344
|
-
this.videoParser = new HevcVideoParser();
|
13345
|
-
}
|
13346
|
-
break;
|
13347
|
-
}
|
13348
|
-
}
|
13349
|
-
if (this.videoParser !== null) {
|
13350
|
-
this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
|
13351
|
-
}
|
12566
|
+
this.videoParser.parseAVCPES(videoTrack, textTrack, pes, false, this._duration);
|
13352
12567
|
}
|
13353
12568
|
videoData = {
|
13354
12569
|
data: [],
|
@@ -13505,28 +12720,14 @@
|
|
13505
12720
|
videoTrack = demuxResult.videoTrack,
|
13506
12721
|
id3Track = demuxResult.id3Track,
|
13507
12722
|
textTrack = demuxResult.textTrack;
|
13508
|
-
var videoData = videoTrack.pesData;
|
13509
|
-
var audioData = audioTrack.pesData;
|
13510
|
-
var id3Data = id3Track.pesData;
|
13511
|
-
// try to parse last PES packets
|
13512
|
-
var pes;
|
13513
|
-
if (videoData && (pes = parsePES(videoData))) {
|
13514
|
-
|
13515
|
-
|
13516
|
-
case 'avc':
|
13517
|
-
this.videoParser = new AvcVideoParser();
|
13518
|
-
break;
|
13519
|
-
case 'hevc':
|
13520
|
-
{
|
13521
|
-
this.videoParser = new HevcVideoParser();
|
13522
|
-
}
|
13523
|
-
break;
|
13524
|
-
}
|
13525
|
-
}
|
13526
|
-
if (this.videoParser !== null) {
|
13527
|
-
this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
|
13528
|
-
videoTrack.pesData = null;
|
13529
|
-
}
|
12723
|
+
var videoData = videoTrack.pesData;
|
12724
|
+
var audioData = audioTrack.pesData;
|
12725
|
+
var id3Data = id3Track.pesData;
|
12726
|
+
// try to parse last PES packets
|
12727
|
+
var pes;
|
12728
|
+
if (videoData && (pes = parsePES(videoData))) {
|
12729
|
+
this.videoParser.parseAVCPES(videoTrack, textTrack, pes, true, this._duration);
|
12730
|
+
videoTrack.pesData = null;
|
13530
12731
|
} else {
|
13531
12732
|
// either avcData null or PES truncated, keep it for next frag parsing
|
13532
12733
|
videoTrack.pesData = videoData;
|
@@ -13858,14 +13059,7 @@
|
|
13858
13059
|
logger.warn('Unsupported EC-3 in M2TS found');
|
13859
13060
|
break;
|
13860
13061
|
case 0x24:
|
13861
|
-
|
13862
|
-
{
|
13863
|
-
if (result.videoPid === -1) {
|
13864
|
-
result.videoPid = pid;
|
13865
|
-
result.segmentVideoCodec = 'hevc';
|
13866
|
-
logger.log('HEVC in M2TS found');
|
13867
|
-
}
|
13868
|
-
}
|
13062
|
+
logger.warn('Unsupported HEVC in M2TS found');
|
13869
13063
|
break;
|
13870
13064
|
}
|
13871
13065
|
// move to the next table entry
|
@@ -14093,8 +13287,6 @@
|
|
14093
13287
|
avc1: [],
|
14094
13288
|
// codingname
|
14095
13289
|
avcC: [],
|
14096
|
-
hvc1: [],
|
14097
|
-
hvcC: [],
|
14098
13290
|
btrt: [],
|
14099
13291
|
dinf: [],
|
14100
13292
|
dref: [],
|
@@ -14522,10 +13714,8 @@
|
|
14522
13714
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
14523
13715
|
}
|
14524
13716
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
14525
|
-
} else if (track.segmentCodec === 'avc') {
|
14526
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
14527
13717
|
} else {
|
14528
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.
|
13718
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
14529
13719
|
}
|
14530
13720
|
};
|
14531
13721
|
MP4.tkhd = function tkhd(track) {
|
@@ -14663,84 +13853,6 @@
|
|
14663
13853
|
var result = appendUint8Array(MP4.FTYP, movie);
|
14664
13854
|
return result;
|
14665
13855
|
};
|
14666
|
-
MP4.hvc1 = function hvc1(track) {
|
14667
|
-
var ps = track.params;
|
14668
|
-
var units = [track.vps, track.sps, track.pps];
|
14669
|
-
var NALuLengthSize = 4;
|
14670
|
-
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]);
|
14671
|
-
|
14672
|
-
// compute hvcC size in bytes
|
14673
|
-
var length = config.length;
|
14674
|
-
for (var i = 0; i < units.length; i += 1) {
|
14675
|
-
length += 3;
|
14676
|
-
for (var j = 0; j < units[i].length; j += 1) {
|
14677
|
-
length += 2 + units[i][j].length;
|
14678
|
-
}
|
14679
|
-
}
|
14680
|
-
var hvcC = new Uint8Array(length);
|
14681
|
-
hvcC.set(config, 0);
|
14682
|
-
length = config.length;
|
14683
|
-
// append parameter set units: one vps, one or more sps and pps
|
14684
|
-
var iMax = units.length - 1;
|
14685
|
-
for (var _i = 0; _i < units.length; _i += 1) {
|
14686
|
-
hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
|
14687
|
-
length += 3;
|
14688
|
-
for (var _j = 0; _j < units[_i].length; _j += 1) {
|
14689
|
-
hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
|
14690
|
-
length += 2;
|
14691
|
-
hvcC.set(units[_i][_j], length);
|
14692
|
-
length += units[_i][_j].length;
|
14693
|
-
}
|
14694
|
-
}
|
14695
|
-
var hvcc = MP4.box(MP4.types.hvcC, hvcC);
|
14696
|
-
var width = track.width;
|
14697
|
-
var height = track.height;
|
14698
|
-
var hSpacing = track.pixelRatio[0];
|
14699
|
-
var vSpacing = track.pixelRatio[1];
|
14700
|
-
return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
|
14701
|
-
// reserved
|
14702
|
-
0x00, 0x00, 0x00,
|
14703
|
-
// reserved
|
14704
|
-
0x00, 0x01,
|
14705
|
-
// data_reference_index
|
14706
|
-
0x00, 0x00,
|
14707
|
-
// pre_defined
|
14708
|
-
0x00, 0x00,
|
14709
|
-
// reserved
|
14710
|
-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
14711
|
-
// pre_defined
|
14712
|
-
width >> 8 & 0xff, width & 0xff,
|
14713
|
-
// width
|
14714
|
-
height >> 8 & 0xff, height & 0xff,
|
14715
|
-
// height
|
14716
|
-
0x00, 0x48, 0x00, 0x00,
|
14717
|
-
// horizresolution
|
14718
|
-
0x00, 0x48, 0x00, 0x00,
|
14719
|
-
// vertresolution
|
14720
|
-
0x00, 0x00, 0x00, 0x00,
|
14721
|
-
// reserved
|
14722
|
-
0x00, 0x01,
|
14723
|
-
// frame_count
|
14724
|
-
0x12, 0x64, 0x61, 0x69, 0x6c,
|
14725
|
-
// dailymotion/hls.js
|
14726
|
-
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,
|
14727
|
-
// compressorname
|
14728
|
-
0x00, 0x18,
|
14729
|
-
// depth = 24
|
14730
|
-
0x11, 0x11]),
|
14731
|
-
// pre_defined = -1
|
14732
|
-
hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
|
14733
|
-
// bufferSizeDB
|
14734
|
-
0x00, 0x2d, 0xc6, 0xc0,
|
14735
|
-
// maxBitrate
|
14736
|
-
0x00, 0x2d, 0xc6, 0xc0])),
|
14737
|
-
// avgBitrate
|
14738
|
-
MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
|
14739
|
-
// hSpacing
|
14740
|
-
hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
|
14741
|
-
// vSpacing
|
14742
|
-
vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
|
14743
|
-
};
|
14744
13856
|
return MP4;
|
14745
13857
|
}();
|
14746
13858
|
MP4.types = void 0;
|
@@ -15142,9 +14254,9 @@
|
|
15142
14254
|
var foundOverlap = delta < -1;
|
15143
14255
|
if (foundHole || foundOverlap) {
|
15144
14256
|
if (foundHole) {
|
15145
|
-
logger.warn(
|
14257
|
+
logger.warn("AVC: " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
|
15146
14258
|
} else {
|
15147
|
-
logger.warn(
|
14259
|
+
logger.warn("AVC: " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
|
15148
14260
|
}
|
15149
14261
|
if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
|
15150
14262
|
firstDTS = nextAvcDts;
|
@@ -15153,24 +14265,12 @@
|
|
15153
14265
|
inputSamples[0].dts = firstDTS;
|
15154
14266
|
inputSamples[0].pts = firstPTS;
|
15155
14267
|
} else {
|
15156
|
-
var isPTSOrderRetained = true;
|
15157
14268
|
for (var _i = 0; _i < inputSamples.length; _i++) {
|
15158
|
-
if (inputSamples[_i].dts > firstPTS
|
14269
|
+
if (inputSamples[_i].dts > firstPTS) {
|
15159
14270
|
break;
|
15160
14271
|
}
|
15161
|
-
var prevPTS = inputSamples[_i].pts;
|
15162
14272
|
inputSamples[_i].dts -= delta;
|
15163
14273
|
inputSamples[_i].pts -= delta;
|
15164
|
-
|
15165
|
-
// check to see if this sample's PTS order has changed
|
15166
|
-
// relative to the next one
|
15167
|
-
if (_i < inputSamples.length - 1) {
|
15168
|
-
var nextSamplePTS = inputSamples[_i + 1].pts;
|
15169
|
-
var currentSamplePTS = inputSamples[_i].pts;
|
15170
|
-
var currentOrder = nextSamplePTS <= currentSamplePTS;
|
15171
|
-
var prevOrder = nextSamplePTS <= prevPTS;
|
15172
|
-
isPTSOrderRetained = currentOrder == prevOrder;
|
15173
|
-
}
|
15174
14274
|
}
|
15175
14275
|
}
|
15176
14276
|
logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
|
@@ -15318,7 +14418,7 @@
|
|
15318
14418
|
}
|
15319
14419
|
}
|
15320
14420
|
}
|
15321
|
-
// next AVC
|
14421
|
+
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
15322
14422
|
mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
|
15323
14423
|
this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
|
15324
14424
|
this.videoSampleDuration = mp4SampleDuration;
|
@@ -15453,7 +14553,7 @@
|
|
15453
14553
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
15454
14554
|
for (var j = 0; j < missing; j++) {
|
15455
14555
|
var newStamp = Math.max(nextPts, 0);
|
15456
|
-
var fillFrame = AAC.getSilentFrame(track.
|
14556
|
+
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15457
14557
|
if (!fillFrame) {
|
15458
14558
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
15459
14559
|
fillFrame = sample.unit.subarray();
|
@@ -15581,7 +14681,7 @@
|
|
15581
14681
|
// samples count of this segment's duration
|
15582
14682
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
15583
14683
|
// silent frame
|
15584
|
-
var silentFrame = AAC.getSilentFrame(track.
|
14684
|
+
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
15585
14685
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
15586
14686
|
// Can't remux if we can't generate a silent frame...
|
15587
14687
|
if (!silentFrame) {
|
@@ -15971,15 +15071,13 @@
|
|
15971
15071
|
duration = transmuxConfig.duration,
|
15972
15072
|
initSegmentData = transmuxConfig.initSegmentData;
|
15973
15073
|
var keyData = getEncryptionType(uintData, decryptdata);
|
15974
|
-
if (keyData &&
|
15074
|
+
if (keyData && keyData.method === 'AES-128') {
|
15975
15075
|
var decrypter = this.getDecrypter();
|
15976
|
-
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
15977
|
-
|
15978
15076
|
// Software decryption is synchronous; webCrypto is not
|
15979
15077
|
if (decrypter.isSync()) {
|
15980
15078
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
15981
15079
|
// data is handled in the flush() call
|
15982
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15080
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
15983
15081
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
15984
15082
|
var loadingParts = chunkMeta.part > -1;
|
15985
15083
|
if (loadingParts) {
|
@@ -15991,7 +15089,7 @@
|
|
15991
15089
|
}
|
15992
15090
|
uintData = new Uint8Array(decryptedData);
|
15993
15091
|
} else {
|
15994
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15092
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
15995
15093
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
15996
15094
|
// the decrypted data has been transmuxed
|
15997
15095
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -16612,7 +15710,7 @@
|
|
16612
15710
|
observer.on(Events.ERROR, forwardMessage);
|
16613
15711
|
|
16614
15712
|
// forward logger events to main thread
|
16615
|
-
var forwardWorkerLogs = function forwardWorkerLogs(
|
15713
|
+
var forwardWorkerLogs = function forwardWorkerLogs() {
|
16616
15714
|
var _loop = function _loop(logFn) {
|
16617
15715
|
var func = function func(message) {
|
16618
15716
|
forwardMessage('workerLog', {
|
@@ -16633,8 +15731,8 @@
|
|
16633
15731
|
{
|
16634
15732
|
var config = JSON.parse(data.config);
|
16635
15733
|
self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
|
16636
|
-
|
16637
|
-
forwardWorkerLogs(
|
15734
|
+
enableLogs(config.debug, data.id);
|
15735
|
+
forwardWorkerLogs();
|
16638
15736
|
forwardMessage('init', null);
|
16639
15737
|
break;
|
16640
15738
|
}
|
@@ -16808,7 +15906,16 @@
|
|
16808
15906
|
this.observer = new EventEmitter();
|
16809
15907
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
16810
15908
|
this.observer.on(Events.ERROR, forwardMessage);
|
16811
|
-
var
|
15909
|
+
var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
|
15910
|
+
isTypeSupported: function isTypeSupported() {
|
15911
|
+
return false;
|
15912
|
+
}
|
15913
|
+
};
|
15914
|
+
var m2tsTypeSupported = {
|
15915
|
+
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
15916
|
+
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
15917
|
+
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
15918
|
+
};
|
16812
15919
|
|
16813
15920
|
// navigator.vendor is not always available in Web Worker
|
16814
15921
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -17092,7 +16199,7 @@
|
|
17092
16199
|
_inheritsLoose(AudioStreamController, _BaseStreamController);
|
17093
16200
|
function AudioStreamController(hls, fragmentTracker, keyLoader) {
|
17094
16201
|
var _this;
|
17095
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
|
16202
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]', PlaylistLevelType.AUDIO) || this;
|
17096
16203
|
_this.videoBuffer = null;
|
17097
16204
|
_this.videoTrackCC = -1;
|
17098
16205
|
_this.waitingVideoCC = -1;
|
@@ -17104,24 +16211,27 @@
|
|
17104
16211
|
_this.flushing = false;
|
17105
16212
|
_this.bufferFlushed = false;
|
17106
16213
|
_this.cachedTrackLoadedData = null;
|
17107
|
-
_this.
|
16214
|
+
_this._registerListeners();
|
17108
16215
|
return _this;
|
17109
16216
|
}
|
17110
16217
|
var _proto = AudioStreamController.prototype;
|
17111
16218
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
17112
|
-
this.
|
16219
|
+
this._unregisterListeners();
|
17113
16220
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
17114
16221
|
this.mainDetails = null;
|
17115
16222
|
this.bufferedTrack = null;
|
17116
16223
|
this.switchingTrack = null;
|
17117
16224
|
};
|
17118
|
-
_proto.
|
17119
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
16225
|
+
_proto._registerListeners = function _registerListeners() {
|
17120
16226
|
var hls = this.hls;
|
16227
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16228
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16229
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17121
16230
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17122
16231
|
hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
17123
16232
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
17124
16233
|
hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16234
|
+
hls.on(Events.ERROR, this.onError, this);
|
17125
16235
|
hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
|
17126
16236
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
17127
16237
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -17129,16 +16239,16 @@
|
|
17129
16239
|
hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
|
17130
16240
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
17131
16241
|
};
|
17132
|
-
_proto.
|
16242
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
17133
16243
|
var hls = this.hls;
|
17134
|
-
|
17135
|
-
|
17136
|
-
|
17137
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
16244
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
16245
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
16246
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
17138
16247
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17139
16248
|
hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
17140
16249
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
17141
16250
|
hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
16251
|
+
hls.off(Events.ERROR, this.onError, this);
|
17142
16252
|
hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
|
17143
16253
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
17144
16254
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -17297,13 +16407,12 @@
|
|
17297
16407
|
trackId = this.trackId;
|
17298
16408
|
var config = hls.config;
|
17299
16409
|
|
17300
|
-
// 1. if
|
17301
|
-
// 2. if video not attached AND
|
16410
|
+
// 1. if video not attached AND
|
17302
16411
|
// start fragment already requested OR start frag prefetch not enabled
|
17303
|
-
//
|
16412
|
+
// 2. if tracks or track not loaded and selected
|
17304
16413
|
// then exit loop
|
17305
16414
|
// => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
|
17306
|
-
if (!
|
16415
|
+
if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
|
17307
16416
|
return;
|
17308
16417
|
}
|
17309
16418
|
var levelInfo = levels[trackId];
|
@@ -17832,7 +16941,7 @@
|
|
17832
16941
|
_inheritsLoose(AudioTrackController, _BasePlaylistControll);
|
17833
16942
|
function AudioTrackController(hls) {
|
17834
16943
|
var _this;
|
17835
|
-
_this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
|
16944
|
+
_this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this;
|
17836
16945
|
_this.tracks = [];
|
17837
16946
|
_this.groupIds = null;
|
17838
16947
|
_this.tracksInGroup = [];
|
@@ -18161,23 +17270,26 @@
|
|
18161
17270
|
_inheritsLoose(SubtitleStreamController, _BaseStreamController);
|
18162
17271
|
function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
|
18163
17272
|
var _this;
|
18164
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
|
17273
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]', PlaylistLevelType.SUBTITLE) || this;
|
18165
17274
|
_this.currentTrackId = -1;
|
18166
17275
|
_this.tracksBuffered = [];
|
18167
17276
|
_this.mainDetails = null;
|
18168
|
-
_this.
|
17277
|
+
_this._registerListeners();
|
18169
17278
|
return _this;
|
18170
17279
|
}
|
18171
17280
|
var _proto = SubtitleStreamController.prototype;
|
18172
17281
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
18173
|
-
this.
|
17282
|
+
this._unregisterListeners();
|
18174
17283
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
18175
17284
|
this.mainDetails = null;
|
18176
17285
|
};
|
18177
|
-
_proto.
|
18178
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
17286
|
+
_proto._registerListeners = function _registerListeners() {
|
18179
17287
|
var hls = this.hls;
|
17288
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17289
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17290
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
18180
17291
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17292
|
+
hls.on(Events.ERROR, this.onError, this);
|
18181
17293
|
hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
18182
17294
|
hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
18183
17295
|
hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -18185,10 +17297,13 @@
|
|
18185
17297
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
18186
17298
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
18187
17299
|
};
|
18188
|
-
_proto.
|
18189
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
17300
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
18190
17301
|
var hls = this.hls;
|
17302
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
17303
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
17304
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
18191
17305
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
17306
|
+
hls.off(Events.ERROR, this.onError, this);
|
18192
17307
|
hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
|
18193
17308
|
hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
|
18194
17309
|
hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
|
@@ -18411,10 +17526,10 @@
|
|
18411
17526
|
return;
|
18412
17527
|
}
|
18413
17528
|
// check to see if the payload needs to be decrypted
|
18414
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
17529
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
18415
17530
|
var startTime = performance.now();
|
18416
17531
|
// decrypt the subtitles
|
18417
|
-
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
17532
|
+
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
18418
17533
|
hls.trigger(Events.ERROR, {
|
18419
17534
|
type: ErrorTypes.MEDIA_ERROR,
|
18420
17535
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -18546,7 +17661,7 @@
|
|
18546
17661
|
_inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
|
18547
17662
|
function SubtitleTrackController(hls) {
|
18548
17663
|
var _this;
|
18549
|
-
_this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
|
17664
|
+
_this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this;
|
18550
17665
|
_this.media = null;
|
18551
17666
|
_this.tracks = [];
|
18552
17667
|
_this.groupIds = null;
|
@@ -18555,12 +17670,12 @@
|
|
18555
17670
|
_this.currentTrack = null;
|
18556
17671
|
_this.selectDefaultTrack = true;
|
18557
17672
|
_this.queuedDefaultTrack = -1;
|
18558
|
-
_this.useTextTrackPolling = false;
|
18559
|
-
_this.subtitlePollingInterval = -1;
|
18560
|
-
_this._subtitleDisplay = true;
|
18561
17673
|
_this.asyncPollTrackChange = function () {
|
18562
17674
|
return _this.pollTrackChange(0);
|
18563
17675
|
};
|
17676
|
+
_this.useTextTrackPolling = false;
|
17677
|
+
_this.subtitlePollingInterval = -1;
|
17678
|
+
_this._subtitleDisplay = true;
|
18564
17679
|
_this.onTextTracksChanged = function () {
|
18565
17680
|
if (!_this.useTextTrackPolling) {
|
18566
17681
|
self.clearInterval(_this.subtitlePollingInterval);
|
@@ -18596,7 +17711,6 @@
|
|
18596
17711
|
this.tracks.length = 0;
|
18597
17712
|
this.tracksInGroup.length = 0;
|
18598
17713
|
this.currentTrack = null;
|
18599
|
-
// @ts-ignore
|
18600
17714
|
this.onTextTracksChanged = this.asyncPollTrackChange = null;
|
18601
17715
|
_BasePlaylistControll.prototype.destroy.call(this);
|
18602
17716
|
};
|
@@ -19070,57 +18184,57 @@
|
|
19070
18184
|
}();
|
19071
18185
|
|
19072
18186
|
var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
|
19073
|
-
var BufferController = /*#__PURE__*/function (
|
19074
|
-
_inheritsLoose(BufferController, _Logger);
|
18187
|
+
var BufferController = /*#__PURE__*/function () {
|
19075
18188
|
function BufferController(hls) {
|
19076
|
-
var _this;
|
19077
|
-
_this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
|
18189
|
+
var _this = this;
|
19078
18190
|
// The level details used to determine duration, target-duration and live
|
19079
|
-
|
18191
|
+
this.details = null;
|
19080
18192
|
// cache the self generated object url to detect hijack of video tag
|
19081
|
-
|
18193
|
+
this._objectUrl = null;
|
19082
18194
|
// A queue of buffer operations which require the SourceBuffer to not be updating upon execution
|
19083
|
-
|
18195
|
+
this.operationQueue = void 0;
|
19084
18196
|
// References to event listeners for each SourceBuffer, so that they can be referenced for event removal
|
19085
|
-
|
19086
|
-
|
18197
|
+
this.listeners = void 0;
|
18198
|
+
this.hls = void 0;
|
19087
18199
|
// The number of BUFFER_CODEC events received before any sourceBuffers are created
|
19088
|
-
|
18200
|
+
this.bufferCodecEventsExpected = 0;
|
19089
18201
|
// The total number of BUFFER_CODEC events received
|
19090
|
-
|
18202
|
+
this._bufferCodecEventsTotal = 0;
|
19091
18203
|
// A reference to the attached media element
|
19092
|
-
|
18204
|
+
this.media = null;
|
19093
18205
|
// A reference to the active media source
|
19094
|
-
|
18206
|
+
this.mediaSource = null;
|
19095
18207
|
// Last MP3 audio chunk appended
|
19096
|
-
|
19097
|
-
|
18208
|
+
this.lastMpegAudioChunk = null;
|
18209
|
+
this.appendSource = void 0;
|
19098
18210
|
// counters
|
19099
|
-
|
18211
|
+
this.appendErrors = {
|
19100
18212
|
audio: 0,
|
19101
18213
|
video: 0,
|
19102
18214
|
audiovideo: 0
|
19103
18215
|
};
|
19104
|
-
|
19105
|
-
|
19106
|
-
|
19107
|
-
|
18216
|
+
this.tracks = {};
|
18217
|
+
this.pendingTracks = {};
|
18218
|
+
this.sourceBuffer = void 0;
|
18219
|
+
this.log = void 0;
|
18220
|
+
this.warn = void 0;
|
18221
|
+
this.error = void 0;
|
18222
|
+
this._onEndStreaming = function (event) {
|
19108
18223
|
if (!_this.hls) {
|
19109
18224
|
return;
|
19110
18225
|
}
|
19111
18226
|
_this.hls.pauseBuffering();
|
19112
18227
|
};
|
19113
|
-
|
18228
|
+
this._onStartStreaming = function (event) {
|
19114
18229
|
if (!_this.hls) {
|
19115
18230
|
return;
|
19116
18231
|
}
|
19117
18232
|
_this.hls.resumeBuffering();
|
19118
18233
|
};
|
19119
18234
|
// Keep as arrow functions so that we can directly reference these functions directly as event listeners
|
19120
|
-
|
19121
|
-
var
|
19122
|
-
|
19123
|
-
mediaSource = _assertThisInitialize.mediaSource;
|
18235
|
+
this._onMediaSourceOpen = function () {
|
18236
|
+
var media = _this.media,
|
18237
|
+
mediaSource = _this.mediaSource;
|
19124
18238
|
_this.log('Media source opened');
|
19125
18239
|
if (media) {
|
19126
18240
|
media.removeEventListener('emptied', _this._onMediaEmptied);
|
@@ -19136,25 +18250,27 @@
|
|
19136
18250
|
}
|
19137
18251
|
_this.checkPendingTracks();
|
19138
18252
|
};
|
19139
|
-
|
18253
|
+
this._onMediaSourceClose = function () {
|
19140
18254
|
_this.log('Media source closed');
|
19141
18255
|
};
|
19142
|
-
|
18256
|
+
this._onMediaSourceEnded = function () {
|
19143
18257
|
_this.log('Media source ended');
|
19144
18258
|
};
|
19145
|
-
|
19146
|
-
var
|
19147
|
-
|
19148
|
-
_objectUrl = _assertThisInitialize2._objectUrl;
|
18259
|
+
this._onMediaEmptied = function () {
|
18260
|
+
var mediaSrc = _this.mediaSrc,
|
18261
|
+
_objectUrl = _this._objectUrl;
|
19149
18262
|
if (mediaSrc !== _objectUrl) {
|
19150
|
-
|
18263
|
+
logger.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
|
19151
18264
|
}
|
19152
18265
|
};
|
19153
|
-
|
19154
|
-
|
19155
|
-
|
19156
|
-
|
19157
|
-
|
18266
|
+
this.hls = hls;
|
18267
|
+
var logPrefix = '[buffer-controller]';
|
18268
|
+
this.appendSource = hls.config.preferManagedMediaSource;
|
18269
|
+
this.log = logger.log.bind(logger, logPrefix);
|
18270
|
+
this.warn = logger.warn.bind(logger, logPrefix);
|
18271
|
+
this.error = logger.error.bind(logger, logPrefix);
|
18272
|
+
this._initSourceBuffer();
|
18273
|
+
this.registerListeners();
|
19158
18274
|
}
|
19159
18275
|
var _proto = BufferController.prototype;
|
19160
18276
|
_proto.hasSourceTypes = function hasSourceTypes() {
|
@@ -19166,12 +18282,6 @@
|
|
19166
18282
|
this.lastMpegAudioChunk = null;
|
19167
18283
|
// @ts-ignore
|
19168
18284
|
this.hls = null;
|
19169
|
-
// @ts-ignore
|
19170
|
-
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
19171
|
-
// @ts-ignore
|
19172
|
-
this._onMediaSourceEnded = null;
|
19173
|
-
// @ts-ignore
|
19174
|
-
this._onStartStreaming = this._onEndStreaming = null;
|
19175
18285
|
};
|
19176
18286
|
_proto.registerListeners = function registerListeners() {
|
19177
18287
|
var hls = this.hls;
|
@@ -19329,7 +18439,6 @@
|
|
19329
18439
|
_this2.resetBuffer(type);
|
19330
18440
|
});
|
19331
18441
|
this._initSourceBuffer();
|
19332
|
-
this.hls.resumeBuffering();
|
19333
18442
|
};
|
19334
18443
|
_proto.resetBuffer = function resetBuffer(type) {
|
19335
18444
|
var sb = this.sourceBuffer[type];
|
@@ -20033,7 +19142,7 @@
|
|
20033
19142
|
}
|
20034
19143
|
}]);
|
20035
19144
|
return BufferController;
|
20036
|
-
}(
|
19145
|
+
}();
|
20037
19146
|
function removeSourceChildren(node) {
|
20038
19147
|
var sourceChildren = node.querySelectorAll('source');
|
20039
19148
|
[].slice.call(sourceChildren).forEach(function (source) {
|
@@ -22472,12 +21581,14 @@
|
|
22472
21581
|
this.cea608Parser1 = this.cea608Parser2 = undefined;
|
22473
21582
|
};
|
22474
21583
|
_proto.initCea608Parsers = function initCea608Parsers() {
|
22475
|
-
|
22476
|
-
|
22477
|
-
|
22478
|
-
|
22479
|
-
|
22480
|
-
|
21584
|
+
if (this.config.enableCEA708Captions && (!this.cea608Parser1 || !this.cea608Parser2)) {
|
21585
|
+
var channel1 = new OutputFilter(this, 'textTrack1');
|
21586
|
+
var channel2 = new OutputFilter(this, 'textTrack2');
|
21587
|
+
var channel3 = new OutputFilter(this, 'textTrack3');
|
21588
|
+
var channel4 = new OutputFilter(this, 'textTrack4');
|
21589
|
+
this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
|
21590
|
+
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21591
|
+
}
|
22481
21592
|
};
|
22482
21593
|
_proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
|
22483
21594
|
// skip cues which overlap more than 50% with previously parsed time ranges
|
@@ -22712,7 +21823,7 @@
|
|
22712
21823
|
return t.label;
|
22713
21824
|
});
|
22714
21825
|
if (unusedTextTracks.length) {
|
22715
|
-
|
21826
|
+
logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
|
22716
21827
|
}
|
22717
21828
|
}
|
22718
21829
|
} else if (this.tracks.length) {
|
@@ -22758,20 +21869,23 @@
|
|
22758
21869
|
return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
|
22759
21870
|
};
|
22760
21871
|
_proto.onFragLoading = function onFragLoading(event, data) {
|
21872
|
+
this.initCea608Parsers();
|
21873
|
+
var cea608Parser1 = this.cea608Parser1,
|
21874
|
+
cea608Parser2 = this.cea608Parser2,
|
21875
|
+
lastCc = this.lastCc,
|
21876
|
+
lastSn = this.lastSn,
|
21877
|
+
lastPartIndex = this.lastPartIndex;
|
21878
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
21879
|
+
return;
|
21880
|
+
}
|
22761
21881
|
// if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
|
22762
|
-
if (
|
21882
|
+
if (data.frag.type === PlaylistLevelType.MAIN) {
|
22763
21883
|
var _data$part$index, _data$part;
|
22764
|
-
var cea608Parser1 = this.cea608Parser1,
|
22765
|
-
cea608Parser2 = this.cea608Parser2,
|
22766
|
-
lastSn = this.lastSn;
|
22767
|
-
if (!cea608Parser1 || !cea608Parser2) {
|
22768
|
-
return;
|
22769
|
-
}
|
22770
21884
|
var _data$frag = data.frag,
|
22771
21885
|
cc = _data$frag.cc,
|
22772
21886
|
sn = _data$frag.sn;
|
22773
|
-
var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
22774
|
-
if (!(sn === lastSn + 1 || sn === lastSn && partIndex ===
|
21887
|
+
var partIndex = (_data$part$index = data == null ? void 0 : (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
21888
|
+
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
|
22775
21889
|
cea608Parser1.reset();
|
22776
21890
|
cea608Parser2.reset();
|
22777
21891
|
}
|
@@ -22827,7 +21941,7 @@
|
|
22827
21941
|
frag: frag
|
22828
21942
|
});
|
22829
21943
|
}, function (error) {
|
22830
|
-
|
21944
|
+
logger.log("Failed to parse IMSC1: " + error);
|
22831
21945
|
hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
|
22832
21946
|
success: false,
|
22833
21947
|
frag: frag,
|
@@ -22865,7 +21979,7 @@
|
|
22865
21979
|
_this5._fallbackToIMSC1(frag, payload);
|
22866
21980
|
}
|
22867
21981
|
// Something went wrong while parsing. Trigger event with success false.
|
22868
|
-
|
21982
|
+
logger.log("Failed to parse VTT cue: " + error);
|
22869
21983
|
if (missingInitPTS && maxAvCC > frag.cc) {
|
22870
21984
|
return;
|
22871
21985
|
}
|
@@ -22927,7 +22041,10 @@
|
|
22927
22041
|
this.captionsTracks = {};
|
22928
22042
|
};
|
22929
22043
|
_proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
|
22930
|
-
|
22044
|
+
this.initCea608Parsers();
|
22045
|
+
var cea608Parser1 = this.cea608Parser1,
|
22046
|
+
cea608Parser2 = this.cea608Parser2;
|
22047
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
22931
22048
|
return;
|
22932
22049
|
}
|
22933
22050
|
var frag = data.frag,
|
@@ -22940,12 +22057,9 @@
|
|
22940
22057
|
for (var i = 0; i < samples.length; i++) {
|
22941
22058
|
var ccBytes = samples[i].bytes;
|
22942
22059
|
if (ccBytes) {
|
22943
|
-
if (!this.cea608Parser1) {
|
22944
|
-
this.initCea608Parsers();
|
22945
|
-
}
|
22946
22060
|
var ccdatas = this.extractCea608Data(ccBytes);
|
22947
|
-
|
22948
|
-
|
22061
|
+
cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22062
|
+
cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22949
22063
|
}
|
22950
22064
|
}
|
22951
22065
|
};
|
@@ -23137,7 +22251,7 @@
|
|
23137
22251
|
var hls = this.hls;
|
23138
22252
|
var maxLevel = this.getMaxLevel(levels.length - 1);
|
23139
22253
|
if (maxLevel !== this.autoLevelCapping) {
|
23140
|
-
|
22254
|
+
logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
|
23141
22255
|
}
|
23142
22256
|
hls.autoLevelCapping = maxLevel;
|
23143
22257
|
if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
|
@@ -23327,10 +22441,10 @@
|
|
23327
22441
|
totalDroppedFrames: droppedFrames
|
23328
22442
|
});
|
23329
22443
|
if (droppedFPS > 0) {
|
23330
|
-
//
|
22444
|
+
// logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
|
23331
22445
|
if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
|
23332
22446
|
var currentLevel = hls.currentLevel;
|
23333
|
-
|
22447
|
+
logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
|
23334
22448
|
if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
|
23335
22449
|
currentLevel = currentLevel - 1;
|
23336
22450
|
hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
|
@@ -23363,6 +22477,7 @@
|
|
23363
22477
|
return FPSController;
|
23364
22478
|
}();
|
23365
22479
|
|
22480
|
+
var LOGGER_PREFIX = '[eme]';
|
23366
22481
|
/**
|
23367
22482
|
* Controller to deal with encrypted media extensions (EME)
|
23368
22483
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
|
@@ -23370,122 +22485,26 @@
|
|
23370
22485
|
* @class
|
23371
22486
|
* @constructor
|
23372
22487
|
*/
|
23373
|
-
var EMEController = /*#__PURE__*/function (
|
23374
|
-
_inheritsLoose(EMEController, _Logger);
|
22488
|
+
var EMEController = /*#__PURE__*/function () {
|
23375
22489
|
function EMEController(hls) {
|
23376
|
-
|
23377
|
-
|
23378
|
-
|
23379
|
-
|
23380
|
-
|
23381
|
-
|
23382
|
-
|
23383
|
-
|
23384
|
-
|
23385
|
-
|
23386
|
-
|
23387
|
-
|
23388
|
-
|
23389
|
-
|
23390
|
-
|
23391
|
-
|
23392
|
-
|
23393
|
-
|
23394
|
-
return;
|
23395
|
-
}
|
23396
|
-
var keyId;
|
23397
|
-
var keySystemDomain;
|
23398
|
-
if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
23399
|
-
// Match sinf keyId to playlist skd://keyId=
|
23400
|
-
var json = bin2str(new Uint8Array(initData));
|
23401
|
-
try {
|
23402
|
-
var sinf = base64Decode(JSON.parse(json).sinf);
|
23403
|
-
var tenc = parseSinf(new Uint8Array(sinf));
|
23404
|
-
if (!tenc) {
|
23405
|
-
return;
|
23406
|
-
}
|
23407
|
-
keyId = tenc.subarray(8, 24);
|
23408
|
-
keySystemDomain = KeySystems.FAIRPLAY;
|
23409
|
-
} catch (error) {
|
23410
|
-
_this.warn('Failed to parse sinf "encrypted" event message initData');
|
23411
|
-
return;
|
23412
|
-
}
|
23413
|
-
} else {
|
23414
|
-
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
23415
|
-
var psshInfo = parsePssh(initData);
|
23416
|
-
if (psshInfo === null) {
|
23417
|
-
return;
|
23418
|
-
}
|
23419
|
-
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
23420
|
-
keyId = psshInfo.data.subarray(8, 24);
|
23421
|
-
}
|
23422
|
-
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
23423
|
-
}
|
23424
|
-
if (!keySystemDomain || !keyId) {
|
23425
|
-
return;
|
23426
|
-
}
|
23427
|
-
var keyIdHex = Hex.hexDump(keyId);
|
23428
|
-
var _assertThisInitialize = _assertThisInitialized(_this),
|
23429
|
-
keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
|
23430
|
-
mediaKeySessions = _assertThisInitialize.mediaKeySessions;
|
23431
|
-
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
23432
|
-
var _loop = function _loop() {
|
23433
|
-
// Match playlist key
|
23434
|
-
var keyContext = mediaKeySessions[i];
|
23435
|
-
var decryptdata = keyContext.decryptdata;
|
23436
|
-
if (decryptdata.pssh || !decryptdata.keyId) {
|
23437
|
-
return 0; // continue
|
23438
|
-
}
|
23439
|
-
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
23440
|
-
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
23441
|
-
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
23442
|
-
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
23443
|
-
decryptdata.pssh = new Uint8Array(initData);
|
23444
|
-
decryptdata.keyId = keyId;
|
23445
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
23446
|
-
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
23447
|
-
});
|
23448
|
-
return 1; // break
|
23449
|
-
}
|
23450
|
-
},
|
23451
|
-
_ret;
|
23452
|
-
for (var i = 0; i < mediaKeySessions.length; i++) {
|
23453
|
-
_ret = _loop();
|
23454
|
-
if (_ret === 0) continue;
|
23455
|
-
if (_ret === 1) break;
|
23456
|
-
}
|
23457
|
-
if (!keySessionContextPromise) {
|
23458
|
-
// Clear-lead key (not encountered in playlist)
|
23459
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
23460
|
-
var _keySystemToKeySystem;
|
23461
|
-
var keySystem = _ref.keySystem,
|
23462
|
-
mediaKeys = _ref.mediaKeys;
|
23463
|
-
_this.throwIfDestroyed();
|
23464
|
-
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
23465
|
-
decryptdata.pssh = new Uint8Array(initData);
|
23466
|
-
decryptdata.keyId = keyId;
|
23467
|
-
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
23468
|
-
_this.throwIfDestroyed();
|
23469
|
-
var keySessionContext = _this.createMediaKeySessionContext({
|
23470
|
-
decryptdata: decryptdata,
|
23471
|
-
keySystem: keySystem,
|
23472
|
-
mediaKeys: mediaKeys
|
23473
|
-
});
|
23474
|
-
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
23475
|
-
});
|
23476
|
-
});
|
23477
|
-
}
|
23478
|
-
keySessionContextPromise.catch(function (error) {
|
23479
|
-
return _this.handleError(error);
|
23480
|
-
});
|
23481
|
-
};
|
23482
|
-
_this.onWaitingForKey = function (event) {
|
23483
|
-
_this.log("\"" + event.type + "\" event");
|
23484
|
-
};
|
23485
|
-
_this.hls = hls;
|
23486
|
-
_this.config = hls.config;
|
23487
|
-
_this.registerListeners();
|
23488
|
-
return _this;
|
22490
|
+
this.hls = void 0;
|
22491
|
+
this.config = void 0;
|
22492
|
+
this.media = null;
|
22493
|
+
this.keyFormatPromise = null;
|
22494
|
+
this.keySystemAccessPromises = {};
|
22495
|
+
this._requestLicenseFailureCount = 0;
|
22496
|
+
this.mediaKeySessions = [];
|
22497
|
+
this.keyIdToKeySessionPromise = {};
|
22498
|
+
this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
22499
|
+
this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
|
22500
|
+
this.onWaitingForKey = this._onWaitingForKey.bind(this);
|
22501
|
+
this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
|
22502
|
+
this.log = logger.log.bind(logger, LOGGER_PREFIX);
|
22503
|
+
this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
|
22504
|
+
this.error = logger.error.bind(logger, LOGGER_PREFIX);
|
22505
|
+
this.hls = hls;
|
22506
|
+
this.config = hls.config;
|
22507
|
+
this.registerListeners();
|
23489
22508
|
}
|
23490
22509
|
var _proto = EMEController.prototype;
|
23491
22510
|
_proto.destroy = function destroy() {
|
@@ -23497,9 +22516,9 @@
|
|
23497
22516
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
23498
22517
|
config.drmSystems = config.drmSystemOptions = {};
|
23499
22518
|
// @ts-ignore
|
23500
|
-
this.hls = this.
|
22519
|
+
this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
|
23501
22520
|
// @ts-ignore
|
23502
|
-
this.
|
22521
|
+
this.config = null;
|
23503
22522
|
};
|
23504
22523
|
_proto.registerListeners = function registerListeners() {
|
23505
22524
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -23538,7 +22557,7 @@
|
|
23538
22557
|
}
|
23539
22558
|
};
|
23540
22559
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
23541
|
-
var
|
22560
|
+
var _this = this;
|
23542
22561
|
var levels = this.hls.levels;
|
23543
22562
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
23544
22563
|
return !!value && a.indexOf(value) === i;
|
@@ -23555,7 +22574,7 @@
|
|
23555
22574
|
return new Promise(function (resolve, reject) {
|
23556
22575
|
var attempt = function attempt(keySystems) {
|
23557
22576
|
var keySystem = keySystems.shift();
|
23558
|
-
|
22577
|
+
_this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
23559
22578
|
return resolve({
|
23560
22579
|
keySystem: keySystem,
|
23561
22580
|
mediaKeys: mediaKeys
|
@@ -23590,7 +22609,7 @@
|
|
23590
22609
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
23591
22610
|
};
|
23592
22611
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
23593
|
-
var
|
22612
|
+
var _this2 = this;
|
23594
22613
|
// This can throw, but is caught in event handler callpath
|
23595
22614
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
23596
22615
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -23602,23 +22621,23 @@
|
|
23602
22621
|
keySystemAccess: keySystemAccess
|
23603
22622
|
};
|
23604
22623
|
keySystemAccess.catch(function (error) {
|
23605
|
-
|
22624
|
+
_this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
23606
22625
|
});
|
23607
22626
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
23608
|
-
|
23609
|
-
var certificateRequest =
|
23610
|
-
|
22627
|
+
_this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
22628
|
+
var certificateRequest = _this2.fetchServerCertificate(keySystem);
|
22629
|
+
_this2.log("Create media-keys for \"" + keySystem + "\"");
|
23611
22630
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
23612
|
-
|
22631
|
+
_this2.log("Media-keys created for \"" + keySystem + "\"");
|
23613
22632
|
return certificateRequest.then(function (certificate) {
|
23614
22633
|
if (certificate) {
|
23615
|
-
return
|
22634
|
+
return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
23616
22635
|
}
|
23617
22636
|
return mediaKeys;
|
23618
22637
|
});
|
23619
22638
|
});
|
23620
22639
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
23621
|
-
|
22640
|
+
_this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
23622
22641
|
});
|
23623
22642
|
return _keySystemAccessPromises.mediaKeys;
|
23624
22643
|
});
|
@@ -23627,10 +22646,10 @@
|
|
23627
22646
|
return keySystemAccessPromises.mediaKeys;
|
23628
22647
|
});
|
23629
22648
|
};
|
23630
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
23631
|
-
var decryptdata =
|
23632
|
-
keySystem =
|
23633
|
-
mediaKeys =
|
22649
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
|
22650
|
+
var decryptdata = _ref.decryptdata,
|
22651
|
+
keySystem = _ref.keySystem,
|
22652
|
+
mediaKeys = _ref.mediaKeys;
|
23634
22653
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
23635
22654
|
var mediaKeysSession = mediaKeys.createSession();
|
23636
22655
|
var mediaKeySessionContext = {
|
@@ -23679,14 +22698,14 @@
|
|
23679
22698
|
return this.keyFormatPromise;
|
23680
22699
|
};
|
23681
22700
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
23682
|
-
var
|
22701
|
+
var _this3 = this;
|
23683
22702
|
return new Promise(function (resolve, reject) {
|
23684
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
22703
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
|
23685
22704
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
23686
22705
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
23687
22706
|
});
|
23688
|
-
return
|
23689
|
-
var keySystem =
|
22707
|
+
return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
|
22708
|
+
var keySystem = _ref2.keySystem;
|
23690
22709
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
23691
22710
|
if (keySystemFormat) {
|
23692
22711
|
resolve(keySystemFormat);
|
@@ -23697,31 +22716,31 @@
|
|
23697
22716
|
});
|
23698
22717
|
};
|
23699
22718
|
_proto.loadKey = function loadKey(data) {
|
23700
|
-
var
|
22719
|
+
var _this4 = this;
|
23701
22720
|
var decryptdata = data.keyInfo.decryptdata;
|
23702
22721
|
var keyId = this.getKeyIdString(decryptdata);
|
23703
22722
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
23704
22723
|
this.log("Starting session for key " + keyDetails);
|
23705
22724
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
23706
22725
|
if (!keySessionContextPromise) {
|
23707
|
-
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (
|
23708
|
-
var keySystem =
|
23709
|
-
mediaKeys =
|
23710
|
-
|
23711
|
-
|
23712
|
-
return
|
23713
|
-
|
23714
|
-
var keySessionContext =
|
22726
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) {
|
22727
|
+
var keySystem = _ref3.keySystem,
|
22728
|
+
mediaKeys = _ref3.mediaKeys;
|
22729
|
+
_this4.throwIfDestroyed();
|
22730
|
+
_this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
22731
|
+
return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22732
|
+
_this4.throwIfDestroyed();
|
22733
|
+
var keySessionContext = _this4.createMediaKeySessionContext({
|
23715
22734
|
keySystem: keySystem,
|
23716
22735
|
mediaKeys: mediaKeys,
|
23717
22736
|
decryptdata: decryptdata
|
23718
22737
|
});
|
23719
22738
|
var scheme = 'cenc';
|
23720
|
-
return
|
22739
|
+
return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
23721
22740
|
});
|
23722
22741
|
});
|
23723
22742
|
keySessionContextPromise.catch(function (error) {
|
23724
|
-
return
|
22743
|
+
return _this4.handleError(error);
|
23725
22744
|
});
|
23726
22745
|
}
|
23727
22746
|
return keySessionContextPromise;
|
@@ -23755,22 +22774,120 @@
|
|
23755
22774
|
var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
|
23756
22775
|
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
23757
22776
|
}
|
23758
|
-
return mediaKeySessionContext;
|
22777
|
+
return mediaKeySessionContext;
|
22778
|
+
};
|
22779
|
+
_proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
|
22780
|
+
if (!keySystemsToAttempt.length) {
|
22781
|
+
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
22782
|
+
}
|
22783
|
+
if (keySystemsToAttempt.length === 0) {
|
22784
|
+
throw new EMEKeyError({
|
22785
|
+
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
22786
|
+
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
22787
|
+
fatal: true
|
22788
|
+
}, "Missing key-system license configuration options " + JSON.stringify({
|
22789
|
+
drmSystems: this.config.drmSystems
|
22790
|
+
}));
|
22791
|
+
}
|
22792
|
+
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22793
|
+
};
|
22794
|
+
_proto._onMediaEncrypted = function _onMediaEncrypted(event) {
|
22795
|
+
var _this5 = this;
|
22796
|
+
var initDataType = event.initDataType,
|
22797
|
+
initData = event.initData;
|
22798
|
+
this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
22799
|
+
|
22800
|
+
// Ignore event when initData is null
|
22801
|
+
if (initData === null) {
|
22802
|
+
return;
|
22803
|
+
}
|
22804
|
+
var keyId;
|
22805
|
+
var keySystemDomain;
|
22806
|
+
if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22807
|
+
// Match sinf keyId to playlist skd://keyId=
|
22808
|
+
var json = bin2str(new Uint8Array(initData));
|
22809
|
+
try {
|
22810
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
22811
|
+
var tenc = parseSinf(new Uint8Array(sinf));
|
22812
|
+
if (!tenc) {
|
22813
|
+
return;
|
22814
|
+
}
|
22815
|
+
keyId = tenc.subarray(8, 24);
|
22816
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
22817
|
+
} catch (error) {
|
22818
|
+
this.warn('Failed to parse sinf "encrypted" event message initData');
|
22819
|
+
return;
|
22820
|
+
}
|
22821
|
+
} else {
|
22822
|
+
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22823
|
+
var psshInfo = parsePssh(initData);
|
22824
|
+
if (psshInfo === null) {
|
22825
|
+
return;
|
22826
|
+
}
|
22827
|
+
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22828
|
+
keyId = psshInfo.data.subarray(8, 24);
|
22829
|
+
}
|
22830
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22831
|
+
}
|
22832
|
+
if (!keySystemDomain || !keyId) {
|
22833
|
+
return;
|
22834
|
+
}
|
22835
|
+
var keyIdHex = Hex.hexDump(keyId);
|
22836
|
+
var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
|
22837
|
+
mediaKeySessions = this.mediaKeySessions;
|
22838
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22839
|
+
var _loop = function _loop() {
|
22840
|
+
// Match playlist key
|
22841
|
+
var keyContext = mediaKeySessions[i];
|
22842
|
+
var decryptdata = keyContext.decryptdata;
|
22843
|
+
if (decryptdata.pssh || !decryptdata.keyId) {
|
22844
|
+
return 0; // continue
|
22845
|
+
}
|
22846
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22847
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22848
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22849
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22850
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22851
|
+
decryptdata.keyId = keyId;
|
22852
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22853
|
+
return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22854
|
+
});
|
22855
|
+
return 1; // break
|
22856
|
+
}
|
22857
|
+
},
|
22858
|
+
_ret;
|
22859
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22860
|
+
_ret = _loop();
|
22861
|
+
if (_ret === 0) continue;
|
22862
|
+
if (_ret === 1) break;
|
22863
|
+
}
|
22864
|
+
if (!keySessionContextPromise) {
|
22865
|
+
// Clear-lead key (not encountered in playlist)
|
22866
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
|
22867
|
+
var _keySystemToKeySystem;
|
22868
|
+
var keySystem = _ref4.keySystem,
|
22869
|
+
mediaKeys = _ref4.mediaKeys;
|
22870
|
+
_this5.throwIfDestroyed();
|
22871
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22872
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22873
|
+
decryptdata.keyId = keyId;
|
22874
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22875
|
+
_this5.throwIfDestroyed();
|
22876
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22877
|
+
decryptdata: decryptdata,
|
22878
|
+
keySystem: keySystem,
|
22879
|
+
mediaKeys: mediaKeys
|
22880
|
+
});
|
22881
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22882
|
+
});
|
22883
|
+
});
|
22884
|
+
}
|
22885
|
+
keySessionContextPromise.catch(function (error) {
|
22886
|
+
return _this5.handleError(error);
|
22887
|
+
});
|
23759
22888
|
};
|
23760
|
-
_proto.
|
23761
|
-
|
23762
|
-
keySystemsToAttempt = getKeySystemsForConfig(this.config);
|
23763
|
-
}
|
23764
|
-
if (keySystemsToAttempt.length === 0) {
|
23765
|
-
throw new EMEKeyError({
|
23766
|
-
type: ErrorTypes.KEY_SYSTEM_ERROR,
|
23767
|
-
details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
|
23768
|
-
fatal: true
|
23769
|
-
}, "Missing key-system license configuration options " + JSON.stringify({
|
23770
|
-
drmSystems: this.config.drmSystems
|
23771
|
-
}));
|
23772
|
-
}
|
23773
|
-
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22889
|
+
_proto._onWaitingForKey = function _onWaitingForKey(event) {
|
22890
|
+
this.log("\"" + event.type + "\" event");
|
23774
22891
|
};
|
23775
22892
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
23776
22893
|
var _this6 = this;
|
@@ -24227,7 +23344,7 @@
|
|
24227
23344
|
}
|
24228
23345
|
};
|
24229
23346
|
return EMEController;
|
24230
|
-
}(
|
23347
|
+
}();
|
24231
23348
|
EMEController.CDMCleanupPromise = void 0;
|
24232
23349
|
var EMEKeyError = /*#__PURE__*/function (_Error) {
|
24233
23350
|
_inheritsLoose(EMEKeyError, _Error);
|
@@ -24375,6 +23492,18 @@
|
|
24375
23492
|
this.params = params;
|
24376
23493
|
};
|
24377
23494
|
|
23495
|
+
/**
|
23496
|
+
* A class to represent structured field tokens when `Symbol` is not available.
|
23497
|
+
*
|
23498
|
+
* @group Structured Field
|
23499
|
+
*
|
23500
|
+
* @beta
|
23501
|
+
*/
|
23502
|
+
var SfToken = function SfToken(description) {
|
23503
|
+
this.description = void 0;
|
23504
|
+
this.description = description;
|
23505
|
+
};
|
23506
|
+
|
24378
23507
|
var DICT = 'Dict';
|
24379
23508
|
|
24380
23509
|
function format(value) {
|
@@ -24398,25 +23527,29 @@
|
|
24398
23527
|
});
|
24399
23528
|
}
|
24400
23529
|
|
24401
|
-
|
24402
|
-
|
23530
|
+
var BARE_ITEM = 'Bare Item';
|
23531
|
+
|
23532
|
+
var BOOLEAN = 'Boolean';
|
23533
|
+
|
23534
|
+
var BYTES = 'Byte Sequence';
|
23535
|
+
|
23536
|
+
var DECIMAL = 'Decimal';
|
23537
|
+
|
23538
|
+
var INTEGER = 'Integer';
|
23539
|
+
|
23540
|
+
function isInvalidInt(value) {
|
23541
|
+
return value < -999999999999999 || 999999999999999 < value;
|
24403
23542
|
}
|
24404
23543
|
|
24405
|
-
|
24406
|
-
* A class to represent structured field tokens when `Symbol` is not available.
|
24407
|
-
*
|
24408
|
-
* @group Structured Field
|
24409
|
-
*
|
24410
|
-
* @beta
|
24411
|
-
*/
|
24412
|
-
var SfToken = function SfToken(description) {
|
24413
|
-
this.description = void 0;
|
24414
|
-
this.description = description;
|
24415
|
-
};
|
23544
|
+
var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
|
24416
23545
|
|
24417
|
-
var
|
23546
|
+
var TOKEN = 'Token';
|
24418
23547
|
|
24419
|
-
var
|
23548
|
+
var KEY = 'Key';
|
23549
|
+
|
23550
|
+
function serializeError(src, type, cause) {
|
23551
|
+
return throwError('serialize', src, type, cause);
|
23552
|
+
}
|
24420
23553
|
|
24421
23554
|
// 4.1.9. Serializing a Boolean
|
24422
23555
|
//
|
@@ -24455,8 +23588,6 @@
|
|
24455
23588
|
return btoa(String.fromCharCode.apply(String, binary));
|
24456
23589
|
}
|
24457
23590
|
|
24458
|
-
var BYTES = 'Byte Sequence';
|
24459
|
-
|
24460
23591
|
// 4.1.8. Serializing a Byte Sequence
|
24461
23592
|
//
|
24462
23593
|
// Given a Byte Sequence as input_bytes, return an ASCII string suitable
|
@@ -24488,12 +23619,6 @@
|
|
24488
23619
|
return ":" + base64encode(value) + ":";
|
24489
23620
|
}
|
24490
23621
|
|
24491
|
-
var INTEGER = 'Integer';
|
24492
|
-
|
24493
|
-
function isInvalidInt(value) {
|
24494
|
-
return value < -999999999999999 || 999999999999999 < value;
|
24495
|
-
}
|
24496
|
-
|
24497
23622
|
// 4.1.4. Serializing an Integer
|
24498
23623
|
//
|
24499
23624
|
// Given an Integer as input_integer, return an ASCII string suitable
|
@@ -24559,8 +23684,6 @@
|
|
24559
23684
|
}
|
24560
23685
|
}
|
24561
23686
|
|
24562
|
-
var DECIMAL = 'Decimal';
|
24563
|
-
|
24564
23687
|
// 4.1.5. Serializing a Decimal
|
24565
23688
|
//
|
24566
23689
|
// Given a decimal number as input_decimal, return an ASCII string
|
@@ -24606,8 +23729,6 @@
|
|
24606
23729
|
|
24607
23730
|
var STRING = 'String';
|
24608
23731
|
|
24609
|
-
var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
|
24610
|
-
|
24611
23732
|
// 4.1.6. Serializing a String
|
24612
23733
|
//
|
24613
23734
|
// Given a String as input_string, return an ASCII string suitable for
|
@@ -24643,8 +23764,6 @@
|
|
24643
23764
|
return symbol.description || symbol.toString().slice(7, -1);
|
24644
23765
|
}
|
24645
23766
|
|
24646
|
-
var TOKEN = 'Token';
|
24647
|
-
|
24648
23767
|
function serializeToken(token) {
|
24649
23768
|
var value = symbolToStr(token);
|
24650
23769
|
if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
|
@@ -24712,8 +23831,6 @@
|
|
24712
23831
|
}
|
24713
23832
|
}
|
24714
23833
|
|
24715
|
-
var KEY = 'Key';
|
24716
|
-
|
24717
23834
|
// 4.1.1.3. Serializing a Key
|
24718
23835
|
//
|
24719
23836
|
// Given a key as input_key, return an ASCII string suitable for use in
|
@@ -24965,6 +24082,36 @@
|
|
24965
24082
|
return toPath.join('/');
|
24966
24083
|
}
|
24967
24084
|
|
24085
|
+
/**
|
24086
|
+
* Generate a random v4 UUID
|
24087
|
+
*
|
24088
|
+
* @returns A random v4 UUID
|
24089
|
+
*
|
24090
|
+
* @group Utils
|
24091
|
+
*
|
24092
|
+
* @beta
|
24093
|
+
*/
|
24094
|
+
function uuid() {
|
24095
|
+
try {
|
24096
|
+
return crypto.randomUUID();
|
24097
|
+
} catch (error) {
|
24098
|
+
try {
|
24099
|
+
var url = URL.createObjectURL(new Blob());
|
24100
|
+
var _uuid = url.toString();
|
24101
|
+
URL.revokeObjectURL(url);
|
24102
|
+
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
24103
|
+
} catch (error) {
|
24104
|
+
var dt = new Date().getTime();
|
24105
|
+
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
24106
|
+
var r = (dt + Math.random() * 16) % 16 | 0;
|
24107
|
+
dt = Math.floor(dt / 16);
|
24108
|
+
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
24109
|
+
});
|
24110
|
+
return _uuid2;
|
24111
|
+
}
|
24112
|
+
}
|
24113
|
+
}
|
24114
|
+
|
24968
24115
|
var toRounded = function toRounded(value) {
|
24969
24116
|
return Math.round(value);
|
24970
24117
|
};
|
@@ -25209,36 +24356,6 @@
|
|
25209
24356
|
return "" + url + separator + query;
|
25210
24357
|
}
|
25211
24358
|
|
25212
|
-
/**
|
25213
|
-
* Generate a random v4 UUID
|
25214
|
-
*
|
25215
|
-
* @returns A random v4 UUID
|
25216
|
-
*
|
25217
|
-
* @group Utils
|
25218
|
-
*
|
25219
|
-
* @beta
|
25220
|
-
*/
|
25221
|
-
function uuid() {
|
25222
|
-
try {
|
25223
|
-
return crypto.randomUUID();
|
25224
|
-
} catch (error) {
|
25225
|
-
try {
|
25226
|
-
var url = URL.createObjectURL(new Blob());
|
25227
|
-
var _uuid = url.toString();
|
25228
|
-
URL.revokeObjectURL(url);
|
25229
|
-
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
25230
|
-
} catch (error) {
|
25231
|
-
var dt = new Date().getTime();
|
25232
|
-
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
25233
|
-
var r = (dt + Math.random() * 16) % 16 | 0;
|
25234
|
-
dt = Math.floor(dt / 16);
|
25235
|
-
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
25236
|
-
});
|
25237
|
-
return _uuid2;
|
25238
|
-
}
|
25239
|
-
}
|
25240
|
-
}
|
25241
|
-
|
25242
24359
|
/**
|
25243
24360
|
* Controller to deal with Common Media Client Data (CMCD)
|
25244
24361
|
* @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
|
@@ -25283,7 +24400,7 @@
|
|
25283
24400
|
su: !_this.initialized
|
25284
24401
|
});
|
25285
24402
|
} catch (error) {
|
25286
|
-
|
24403
|
+
logger.warn('Could not generate manifest CMCD data.', error);
|
25287
24404
|
}
|
25288
24405
|
};
|
25289
24406
|
/**
|
@@ -25303,15 +24420,9 @@
|
|
25303
24420
|
data.tb = _this.getTopBandwidth(ot) / 1000;
|
25304
24421
|
data.bl = _this.getBufferLength(ot);
|
25305
24422
|
}
|
25306
|
-
var next = _this.getNextFrag(fragment);
|
25307
|
-
if (next) {
|
25308
|
-
if (next.url && next.url !== fragment.url) {
|
25309
|
-
data.nor = next.url;
|
25310
|
-
}
|
25311
|
-
}
|
25312
24423
|
_this.apply(context, data);
|
25313
24424
|
} catch (error) {
|
25314
|
-
|
24425
|
+
logger.warn('Could not generate segment CMCD data.', error);
|
25315
24426
|
}
|
25316
24427
|
};
|
25317
24428
|
this.hls = hls;
|
@@ -25403,7 +24514,7 @@
|
|
25403
24514
|
data.su = this.buffering;
|
25404
24515
|
}
|
25405
24516
|
|
25406
|
-
// TODO: Implement rtp, nrr, dl
|
24517
|
+
// TODO: Implement rtp, nrr, nor, dl
|
25407
24518
|
|
25408
24519
|
var includeKeys = this.includeKeys;
|
25409
24520
|
if (includeKeys) {
|
@@ -25412,31 +24523,18 @@
|
|
25412
24523
|
return acc;
|
25413
24524
|
}, {});
|
25414
24525
|
}
|
25415
|
-
var options = {
|
25416
|
-
baseUrl: context.url
|
25417
|
-
};
|
25418
24526
|
if (this.useHeaders) {
|
25419
24527
|
if (!context.headers) {
|
25420
24528
|
context.headers = {};
|
25421
24529
|
}
|
25422
|
-
appendCmcdHeaders(context.headers, data
|
24530
|
+
appendCmcdHeaders(context.headers, data);
|
25423
24531
|
} else {
|
25424
|
-
context.url = appendCmcdQuery(context.url, data
|
24532
|
+
context.url = appendCmcdQuery(context.url, data);
|
25425
24533
|
}
|
25426
24534
|
};
|
25427
|
-
_proto.getNextFrag = function getNextFrag(fragment) {
|
25428
|
-
var _this$hls$levels$frag;
|
25429
|
-
var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
|
25430
|
-
if (levelDetails) {
|
25431
|
-
var index = fragment.sn - levelDetails.startSN;
|
25432
|
-
return levelDetails.fragments[index + 1];
|
25433
|
-
}
|
25434
|
-
return undefined;
|
25435
|
-
}
|
25436
|
-
|
25437
24535
|
/**
|
25438
24536
|
* The CMCD object type.
|
25439
|
-
|
24537
|
+
*/
|
25440
24538
|
_proto.getObjectType = function getObjectType(fragment) {
|
25441
24539
|
var type = fragment.type;
|
25442
24540
|
if (type === 'subtitle') {
|
@@ -25572,28 +24670,26 @@
|
|
25572
24670
|
}();
|
25573
24671
|
|
25574
24672
|
var PATHWAY_PENALTY_DURATION_MS = 300000;
|
25575
|
-
var ContentSteeringController = /*#__PURE__*/function (
|
25576
|
-
_inheritsLoose(ContentSteeringController, _Logger);
|
24673
|
+
var ContentSteeringController = /*#__PURE__*/function () {
|
25577
24674
|
function ContentSteeringController(hls) {
|
25578
|
-
|
25579
|
-
|
25580
|
-
|
25581
|
-
|
25582
|
-
|
25583
|
-
|
25584
|
-
|
25585
|
-
|
25586
|
-
|
25587
|
-
|
25588
|
-
|
25589
|
-
|
25590
|
-
|
25591
|
-
|
25592
|
-
|
25593
|
-
|
25594
|
-
|
25595
|
-
|
25596
|
-
return _this;
|
24675
|
+
this.hls = void 0;
|
24676
|
+
this.log = void 0;
|
24677
|
+
this.loader = null;
|
24678
|
+
this.uri = null;
|
24679
|
+
this.pathwayId = '.';
|
24680
|
+
this.pathwayPriority = null;
|
24681
|
+
this.timeToLoad = 300;
|
24682
|
+
this.reloadTimer = -1;
|
24683
|
+
this.updated = 0;
|
24684
|
+
this.started = false;
|
24685
|
+
this.enabled = true;
|
24686
|
+
this.levels = null;
|
24687
|
+
this.audioTracks = null;
|
24688
|
+
this.subtitleTracks = null;
|
24689
|
+
this.penalizedPathways = {};
|
24690
|
+
this.hls = hls;
|
24691
|
+
this.log = logger.log.bind(logger, "[content-steering]:");
|
24692
|
+
this.registerListeners();
|
25597
24693
|
}
|
25598
24694
|
var _proto = ContentSteeringController.prototype;
|
25599
24695
|
_proto.registerListeners = function registerListeners() {
|
@@ -25714,7 +24810,7 @@
|
|
25714
24810
|
errorAction.resolved = this.pathwayId !== errorPathway;
|
25715
24811
|
}
|
25716
24812
|
if (!errorAction.resolved) {
|
25717
|
-
|
24813
|
+
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));
|
25718
24814
|
}
|
25719
24815
|
}
|
25720
24816
|
};
|
@@ -25794,7 +24890,7 @@
|
|
25794
24890
|
return defaultPathway;
|
25795
24891
|
};
|
25796
24892
|
_proto.clonePathways = function clonePathways(pathwayClones) {
|
25797
|
-
var
|
24893
|
+
var _this = this;
|
25798
24894
|
var levels = this.levels;
|
25799
24895
|
if (!levels) {
|
25800
24896
|
return;
|
@@ -25810,7 +24906,7 @@
|
|
25810
24906
|
})) {
|
25811
24907
|
return;
|
25812
24908
|
}
|
25813
|
-
var clonedVariants =
|
24909
|
+
var clonedVariants = _this.getLevelsForPathway(baseId).map(function (baseLevel) {
|
25814
24910
|
var attributes = new AttrList(baseLevel.attrs);
|
25815
24911
|
attributes['PATHWAY-ID'] = cloneId;
|
25816
24912
|
var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
|
@@ -25847,12 +24943,12 @@
|
|
25847
24943
|
return clonedLevel;
|
25848
24944
|
});
|
25849
24945
|
levels.push.apply(levels, clonedVariants);
|
25850
|
-
cloneRenditionGroups(
|
25851
|
-
cloneRenditionGroups(
|
24946
|
+
cloneRenditionGroups(_this.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
|
24947
|
+
cloneRenditionGroups(_this.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
|
25852
24948
|
});
|
25853
24949
|
};
|
25854
24950
|
_proto.loadSteeringManifest = function loadSteeringManifest(uri) {
|
25855
|
-
var
|
24951
|
+
var _this2 = this;
|
25856
24952
|
var config = this.hls.config;
|
25857
24953
|
var Loader = config.loader;
|
25858
24954
|
if (this.loader) {
|
@@ -25887,87 +24983,87 @@
|
|
25887
24983
|
};
|
25888
24984
|
var callbacks = {
|
25889
24985
|
onSuccess: function onSuccess(response, stats, context, networkDetails) {
|
25890
|
-
|
24986
|
+
_this2.log("Loaded steering manifest: \"" + url + "\"");
|
25891
24987
|
var steeringData = response.data;
|
25892
|
-
if (
|
25893
|
-
|
24988
|
+
if (steeringData.VERSION !== 1) {
|
24989
|
+
_this2.log("Steering VERSION " + steeringData.VERSION + " not supported!");
|
25894
24990
|
return;
|
25895
24991
|
}
|
25896
|
-
|
25897
|
-
|
24992
|
+
_this2.updated = performance.now();
|
24993
|
+
_this2.timeToLoad = steeringData.TTL;
|
25898
24994
|
var reloadUri = steeringData['RELOAD-URI'],
|
25899
24995
|
pathwayClones = steeringData['PATHWAY-CLONES'],
|
25900
24996
|
pathwayPriority = steeringData['PATHWAY-PRIORITY'];
|
25901
24997
|
if (reloadUri) {
|
25902
24998
|
try {
|
25903
|
-
|
24999
|
+
_this2.uri = new self.URL(reloadUri, url).href;
|
25904
25000
|
} catch (error) {
|
25905
|
-
|
25906
|
-
|
25001
|
+
_this2.enabled = false;
|
25002
|
+
_this2.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
|
25907
25003
|
return;
|
25908
25004
|
}
|
25909
25005
|
}
|
25910
|
-
|
25006
|
+
_this2.scheduleRefresh(_this2.uri || context.url);
|
25911
25007
|
if (pathwayClones) {
|
25912
|
-
|
25008
|
+
_this2.clonePathways(pathwayClones);
|
25913
25009
|
}
|
25914
25010
|
var loadedSteeringData = {
|
25915
25011
|
steeringManifest: steeringData,
|
25916
25012
|
url: url.toString()
|
25917
25013
|
};
|
25918
|
-
|
25014
|
+
_this2.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
|
25919
25015
|
if (pathwayPriority) {
|
25920
|
-
|
25016
|
+
_this2.updatePathwayPriority(pathwayPriority);
|
25921
25017
|
}
|
25922
25018
|
},
|
25923
25019
|
onError: function onError(error, context, networkDetails, stats) {
|
25924
|
-
|
25925
|
-
|
25020
|
+
_this2.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
|
25021
|
+
_this2.stopLoad();
|
25926
25022
|
if (error.code === 410) {
|
25927
|
-
|
25928
|
-
|
25023
|
+
_this2.enabled = false;
|
25024
|
+
_this2.log("Steering manifest " + context.url + " no longer available");
|
25929
25025
|
return;
|
25930
25026
|
}
|
25931
|
-
var ttl =
|
25027
|
+
var ttl = _this2.timeToLoad * 1000;
|
25932
25028
|
if (error.code === 429) {
|
25933
|
-
var loader =
|
25029
|
+
var loader = _this2.loader;
|
25934
25030
|
if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
|
25935
25031
|
var retryAfter = loader.getResponseHeader('Retry-After');
|
25936
25032
|
if (retryAfter) {
|
25937
25033
|
ttl = parseFloat(retryAfter) * 1000;
|
25938
25034
|
}
|
25939
25035
|
}
|
25940
|
-
|
25036
|
+
_this2.log("Steering manifest " + context.url + " rate limited");
|
25941
25037
|
return;
|
25942
25038
|
}
|
25943
|
-
|
25039
|
+
_this2.scheduleRefresh(_this2.uri || context.url, ttl);
|
25944
25040
|
},
|
25945
25041
|
onTimeout: function onTimeout(stats, context, networkDetails) {
|
25946
|
-
|
25947
|
-
|
25042
|
+
_this2.log("Timeout loading steering manifest (" + context.url + ")");
|
25043
|
+
_this2.scheduleRefresh(_this2.uri || context.url);
|
25948
25044
|
}
|
25949
25045
|
};
|
25950
25046
|
this.log("Requesting steering manifest: " + url);
|
25951
25047
|
this.loader.load(context, loaderConfig, callbacks);
|
25952
25048
|
};
|
25953
25049
|
_proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
|
25954
|
-
var
|
25050
|
+
var _this3 = this;
|
25955
25051
|
if (ttlMs === void 0) {
|
25956
25052
|
ttlMs = this.timeToLoad * 1000;
|
25957
25053
|
}
|
25958
25054
|
this.clearTimeout();
|
25959
25055
|
this.reloadTimer = self.setTimeout(function () {
|
25960
|
-
var
|
25961
|
-
var media = (
|
25056
|
+
var _this3$hls;
|
25057
|
+
var media = (_this3$hls = _this3.hls) == null ? void 0 : _this3$hls.media;
|
25962
25058
|
if (media && !media.ended) {
|
25963
|
-
|
25059
|
+
_this3.loadSteeringManifest(uri);
|
25964
25060
|
return;
|
25965
25061
|
}
|
25966
|
-
|
25062
|
+
_this3.scheduleRefresh(uri, _this3.timeToLoad * 1000);
|
25967
25063
|
}, ttlMs);
|
25968
25064
|
};
|
25969
25065
|
return ContentSteeringController;
|
25970
|
-
}(
|
25066
|
+
}();
|
25971
25067
|
function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
|
25972
25068
|
if (!tracks) {
|
25973
25069
|
return;
|
@@ -26867,7 +25963,7 @@
|
|
26867
25963
|
/**
|
26868
25964
|
* @ignore
|
26869
25965
|
*/
|
26870
|
-
function mergeConfig(defaultConfig, userConfig
|
25966
|
+
function mergeConfig(defaultConfig, userConfig) {
|
26871
25967
|
if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
|
26872
25968
|
throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
|
26873
25969
|
}
|
@@ -26937,7 +26033,7 @@
|
|
26937
26033
|
/**
|
26938
26034
|
* @ignore
|
26939
26035
|
*/
|
26940
|
-
function enableStreamingMode(config
|
26036
|
+
function enableStreamingMode(config) {
|
26941
26037
|
var currentLoader = config.loader;
|
26942
26038
|
if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
|
26943
26039
|
// If a developer has configured their own loader, respect that choice
|
@@ -26954,11 +26050,12 @@
|
|
26954
26050
|
}
|
26955
26051
|
}
|
26956
26052
|
|
26053
|
+
var chromeOrFirefox;
|
26957
26054
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
26958
26055
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
26959
26056
|
function LevelController(hls, contentSteeringController) {
|
26960
26057
|
var _this;
|
26961
|
-
_this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
|
26058
|
+
_this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this;
|
26962
26059
|
_this._levels = [];
|
26963
26060
|
_this._firstLevel = -1;
|
26964
26061
|
_this._maxAutoLevel = -1;
|
@@ -27027,13 +26124,21 @@
|
|
27027
26124
|
var videoCodecFound = false;
|
27028
26125
|
var audioCodecFound = false;
|
27029
26126
|
data.levels.forEach(function (levelParsed) {
|
27030
|
-
var _videoCodec;
|
26127
|
+
var _audioCodec, _videoCodec;
|
27031
26128
|
var attributes = levelParsed.attrs;
|
26129
|
+
|
26130
|
+
// erase audio codec info if browser does not support mp4a.40.34.
|
26131
|
+
// demuxer will autodetect codec and fallback to mpeg/audio
|
27032
26132
|
var audioCodec = levelParsed.audioCodec,
|
27033
26133
|
videoCodec = levelParsed.videoCodec;
|
26134
|
+
if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
|
26135
|
+
chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
|
26136
|
+
if (chromeOrFirefox) {
|
26137
|
+
levelParsed.audioCodec = audioCodec = undefined;
|
26138
|
+
}
|
26139
|
+
}
|
27034
26140
|
if (audioCodec) {
|
27035
|
-
|
27036
|
-
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
26141
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
|
27037
26142
|
}
|
27038
26143
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
27039
26144
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -27265,12 +26370,7 @@
|
|
27265
26370
|
if (curLevel.fragmentError === 0) {
|
27266
26371
|
curLevel.loadError = 0;
|
27267
26372
|
}
|
27268
|
-
|
27269
|
-
var previousDetails = curLevel.details;
|
27270
|
-
if (previousDetails === data.details && previousDetails.advanced) {
|
27271
|
-
previousDetails = undefined;
|
27272
|
-
}
|
27273
|
-
this.playlistLoaded(level, data, previousDetails);
|
26373
|
+
this.playlistLoaded(level, data, curLevel.details);
|
27274
26374
|
} else if ((_data$deliveryDirecti2 = data.deliveryDirectives) != null && _data$deliveryDirecti2.skip) {
|
27275
26375
|
// received a delta playlist update that cannot be merged
|
27276
26376
|
details.deltaUpdateFailed = true;
|
@@ -27646,8 +26746,6 @@
|
|
27646
26746
|
}
|
27647
26747
|
return this.loadKeyEME(keyInfo, frag);
|
27648
26748
|
case 'AES-128':
|
27649
|
-
case 'AES-256':
|
27650
|
-
case 'AES-256-CTR':
|
27651
26749
|
return this.loadKeyHTTP(keyInfo, frag);
|
27652
26750
|
default:
|
27653
26751
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -27787,26 +26885,21 @@
|
|
27787
26885
|
var MAX_START_GAP_JUMP = 2.0;
|
27788
26886
|
var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
|
27789
26887
|
var SKIP_BUFFER_RANGE_START = 0.05;
|
27790
|
-
var GapController = /*#__PURE__*/function (
|
27791
|
-
_inheritsLoose(GapController, _Logger);
|
26888
|
+
var GapController = /*#__PURE__*/function () {
|
27792
26889
|
function GapController(config, media, fragmentTracker, hls) {
|
27793
|
-
|
27794
|
-
|
27795
|
-
|
27796
|
-
|
27797
|
-
|
27798
|
-
|
27799
|
-
|
27800
|
-
|
27801
|
-
|
27802
|
-
|
27803
|
-
|
27804
|
-
|
27805
|
-
|
27806
|
-
_this.media = media;
|
27807
|
-
_this.fragmentTracker = fragmentTracker;
|
27808
|
-
_this.hls = hls;
|
27809
|
-
return _this;
|
26890
|
+
this.config = void 0;
|
26891
|
+
this.media = null;
|
26892
|
+
this.fragmentTracker = void 0;
|
26893
|
+
this.hls = void 0;
|
26894
|
+
this.nudgeRetry = 0;
|
26895
|
+
this.stallReported = false;
|
26896
|
+
this.stalled = null;
|
26897
|
+
this.moved = false;
|
26898
|
+
this.seeking = false;
|
26899
|
+
this.config = config;
|
26900
|
+
this.media = media;
|
26901
|
+
this.fragmentTracker = fragmentTracker;
|
26902
|
+
this.hls = hls;
|
27810
26903
|
}
|
27811
26904
|
var _proto = GapController.prototype;
|
27812
26905
|
_proto.destroy = function destroy() {
|
@@ -27821,7 +26914,7 @@
|
|
27821
26914
|
*
|
27822
26915
|
* @param lastCurrentTime - Previously read playhead position
|
27823
26916
|
*/;
|
27824
|
-
_proto.poll = function poll(lastCurrentTime, activeFrag
|
26917
|
+
_proto.poll = function poll(lastCurrentTime, activeFrag) {
|
27825
26918
|
var config = this.config,
|
27826
26919
|
media = this.media,
|
27827
26920
|
stalled = this.stalled;
|
@@ -27836,7 +26929,6 @@
|
|
27836
26929
|
|
27837
26930
|
// The playhead is moving, no-op
|
27838
26931
|
if (currentTime !== lastCurrentTime) {
|
27839
|
-
this.ended = 0;
|
27840
26932
|
this.moved = true;
|
27841
26933
|
if (!seeking) {
|
27842
26934
|
this.nudgeRetry = 0;
|
@@ -27845,7 +26937,7 @@
|
|
27845
26937
|
// The playhead is now moving, but was previously stalled
|
27846
26938
|
if (this.stallReported) {
|
27847
26939
|
var _stalledDuration = self.performance.now() - stalled;
|
27848
|
-
|
26940
|
+
logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
|
27849
26941
|
this.stallReported = false;
|
27850
26942
|
}
|
27851
26943
|
this.stalled = null;
|
@@ -27881,6 +26973,7 @@
|
|
27881
26973
|
// Skip start gaps if we haven't played, but the last poll detected the start of a stall
|
27882
26974
|
// The addition poll gives the browser a chance to jump the gap for us
|
27883
26975
|
if (!this.moved && this.stalled !== null) {
|
26976
|
+
var _level$details;
|
27884
26977
|
// There is no playable buffer (seeked, waiting for buffer)
|
27885
26978
|
var isBuffered = bufferInfo.len > 0;
|
27886
26979
|
if (!isBuffered && !nextStart) {
|
@@ -27892,8 +26985,9 @@
|
|
27892
26985
|
// When joining a live stream with audio tracks, account for live playlist window sliding by allowing
|
27893
26986
|
// a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
|
27894
26987
|
// that begins over 1 target duration after the video start position.
|
27895
|
-
var
|
27896
|
-
var
|
26988
|
+
var level = this.hls.levels ? this.hls.levels[this.hls.currentLevel] : null;
|
26989
|
+
var isLive = level == null ? void 0 : (_level$details = level.details) == null ? void 0 : _level$details.live;
|
26990
|
+
var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP;
|
27897
26991
|
var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
|
27898
26992
|
if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
|
27899
26993
|
if (!media.paused) {
|
@@ -27911,17 +27005,6 @@
|
|
27911
27005
|
}
|
27912
27006
|
var stalledDuration = tnow - stalled;
|
27913
27007
|
if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
|
27914
|
-
// Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
|
27915
|
-
if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
|
27916
|
-
if (stalledDuration < 1000 || this.ended) {
|
27917
|
-
return;
|
27918
|
-
}
|
27919
|
-
this.ended = currentTime;
|
27920
|
-
this.hls.trigger(Events.MEDIA_ENDED, {
|
27921
|
-
stalled: true
|
27922
|
-
});
|
27923
|
-
return;
|
27924
|
-
}
|
27925
27008
|
// Report stalling after trying to fix
|
27926
27009
|
this._reportStall(bufferInfo);
|
27927
27010
|
if (!this.media) {
|
@@ -27963,7 +27046,7 @@
|
|
27963
27046
|
// needs to cross some sort of threshold covering all source-buffers content
|
27964
27047
|
// to start playing properly.
|
27965
27048
|
if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
|
27966
|
-
|
27049
|
+
logger.warn('Trying to nudge playhead over buffer-hole');
|
27967
27050
|
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
|
27968
27051
|
// We only try to jump the hole if it's under the configured size
|
27969
27052
|
// Reset stalled so to rearm watchdog timer
|
@@ -27985,7 +27068,7 @@
|
|
27985
27068
|
// Report stalled error once
|
27986
27069
|
this.stallReported = true;
|
27987
27070
|
var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
|
27988
|
-
|
27071
|
+
logger.warn(error.message);
|
27989
27072
|
hls.trigger(Events.ERROR, {
|
27990
27073
|
type: ErrorTypes.MEDIA_ERROR,
|
27991
27074
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -28049,7 +27132,7 @@
|
|
28049
27132
|
}
|
28050
27133
|
}
|
28051
27134
|
var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
|
28052
|
-
|
27135
|
+
logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
|
28053
27136
|
this.moved = true;
|
28054
27137
|
this.stalled = null;
|
28055
27138
|
media.currentTime = targetTime;
|
@@ -28088,7 +27171,7 @@
|
|
28088
27171
|
var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
|
28089
27172
|
// playback stalled in buffered area ... let's nudge currentTime to try to overcome this
|
28090
27173
|
var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
|
28091
|
-
|
27174
|
+
logger.warn(error.message);
|
28092
27175
|
media.currentTime = targetTime;
|
28093
27176
|
hls.trigger(Events.ERROR, {
|
28094
27177
|
type: ErrorTypes.MEDIA_ERROR,
|
@@ -28098,7 +27181,7 @@
|
|
28098
27181
|
});
|
28099
27182
|
} else {
|
28100
27183
|
var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
|
28101
|
-
|
27184
|
+
logger.error(_error.message);
|
28102
27185
|
hls.trigger(Events.ERROR, {
|
28103
27186
|
type: ErrorTypes.MEDIA_ERROR,
|
28104
27187
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
@@ -28108,14 +27191,14 @@
|
|
28108
27191
|
}
|
28109
27192
|
};
|
28110
27193
|
return GapController;
|
28111
|
-
}(
|
27194
|
+
}();
|
28112
27195
|
|
28113
27196
|
var TICK_INTERVAL = 100; // how often to tick in ms
|
28114
27197
|
var StreamController = /*#__PURE__*/function (_BaseStreamController) {
|
28115
27198
|
_inheritsLoose(StreamController, _BaseStreamController);
|
28116
27199
|
function StreamController(hls, fragmentTracker, keyLoader) {
|
28117
27200
|
var _this;
|
28118
|
-
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
|
27201
|
+
_this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]', PlaylistLevelType.MAIN) || this;
|
28119
27202
|
_this.audioCodecSwap = false;
|
28120
27203
|
_this.gapController = null;
|
28121
27204
|
_this.level = -1;
|
@@ -28123,43 +27206,27 @@
|
|
28123
27206
|
_this.altAudio = false;
|
28124
27207
|
_this.audioOnly = false;
|
28125
27208
|
_this.fragPlaying = null;
|
27209
|
+
_this.onvplaying = null;
|
27210
|
+
_this.onvseeked = null;
|
28126
27211
|
_this.fragLastKbps = 0;
|
28127
27212
|
_this.couldBacktrack = false;
|
28128
27213
|
_this.backtrackFragment = null;
|
28129
27214
|
_this.audioCodecSwitch = false;
|
28130
27215
|
_this.videoBuffer = null;
|
28131
|
-
_this.
|
28132
|
-
// tick to speed up FRAG_CHANGED triggering
|
28133
|
-
_this.tick();
|
28134
|
-
};
|
28135
|
-
_this.onMediaSeeked = function () {
|
28136
|
-
var media = _this.media;
|
28137
|
-
var currentTime = media ? media.currentTime : null;
|
28138
|
-
if (isFiniteNumber(currentTime)) {
|
28139
|
-
_this.log("Media seeked to " + currentTime.toFixed(3));
|
28140
|
-
}
|
28141
|
-
|
28142
|
-
// If seeked was issued before buffer was appended do not tick immediately
|
28143
|
-
var bufferInfo = _this.getMainFwdBufferInfo();
|
28144
|
-
if (bufferInfo === null || bufferInfo.len === 0) {
|
28145
|
-
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
28146
|
-
return;
|
28147
|
-
}
|
28148
|
-
|
28149
|
-
// tick to speed up FRAG_CHANGED triggering
|
28150
|
-
_this.tick();
|
28151
|
-
};
|
28152
|
-
_this.registerListeners();
|
27216
|
+
_this._registerListeners();
|
28153
27217
|
return _this;
|
28154
27218
|
}
|
28155
27219
|
var _proto = StreamController.prototype;
|
28156
|
-
_proto.
|
28157
|
-
_BaseStreamController.prototype.registerListeners.call(this);
|
27220
|
+
_proto._registerListeners = function _registerListeners() {
|
28158
27221
|
var hls = this.hls;
|
27222
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27223
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27224
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
28159
27225
|
hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
28160
27226
|
hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
|
28161
27227
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
28162
27228
|
hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27229
|
+
hls.on(Events.ERROR, this.onError, this);
|
28163
27230
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
28164
27231
|
hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
28165
27232
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -28167,12 +27234,15 @@
|
|
28167
27234
|
hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
|
28168
27235
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
28169
27236
|
};
|
28170
|
-
_proto.
|
28171
|
-
_BaseStreamController.prototype.unregisterListeners.call(this);
|
27237
|
+
_proto._unregisterListeners = function _unregisterListeners() {
|
28172
27238
|
var hls = this.hls;
|
27239
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
27240
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
27241
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
28173
27242
|
hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
28174
27243
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
28175
27244
|
hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
|
27245
|
+
hls.off(Events.ERROR, this.onError, this);
|
28176
27246
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
28177
27247
|
hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
28178
27248
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -28181,9 +27251,7 @@
|
|
28181
27251
|
hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
28182
27252
|
};
|
28183
27253
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
28184
|
-
|
28185
|
-
this.onMediaPlaying = this.onMediaSeeked = null;
|
28186
|
-
this.unregisterListeners();
|
27254
|
+
this._unregisterListeners();
|
28187
27255
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
28188
27256
|
};
|
28189
27257
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -28293,7 +27361,7 @@
|
|
28293
27361
|
if (this.altAudio && this.audioOnly) {
|
28294
27362
|
return;
|
28295
27363
|
}
|
28296
|
-
if (!
|
27364
|
+
if (!(levels != null && levels[level])) {
|
28297
27365
|
return;
|
28298
27366
|
}
|
28299
27367
|
var levelInfo = levels[level];
|
@@ -28499,15 +27567,18 @@
|
|
28499
27567
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
28500
27568
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
28501
27569
|
var media = data.media;
|
28502
|
-
|
28503
|
-
|
27570
|
+
this.onvplaying = this.onMediaPlaying.bind(this);
|
27571
|
+
this.onvseeked = this.onMediaSeeked.bind(this);
|
27572
|
+
media.addEventListener('playing', this.onvplaying);
|
27573
|
+
media.addEventListener('seeked', this.onvseeked);
|
28504
27574
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
28505
27575
|
};
|
28506
27576
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
28507
27577
|
var media = this.media;
|
28508
|
-
if (media) {
|
28509
|
-
media.removeEventListener('playing', this.
|
28510
|
-
media.removeEventListener('seeked', this.
|
27578
|
+
if (media && this.onvplaying && this.onvseeked) {
|
27579
|
+
media.removeEventListener('playing', this.onvplaying);
|
27580
|
+
media.removeEventListener('seeked', this.onvseeked);
|
27581
|
+
this.onvplaying = this.onvseeked = null;
|
28511
27582
|
this.videoBuffer = null;
|
28512
27583
|
}
|
28513
27584
|
this.fragPlaying = null;
|
@@ -28517,6 +27588,27 @@
|
|
28517
27588
|
}
|
28518
27589
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
28519
27590
|
};
|
27591
|
+
_proto.onMediaPlaying = function onMediaPlaying() {
|
27592
|
+
// tick to speed up FRAG_CHANGED triggering
|
27593
|
+
this.tick();
|
27594
|
+
};
|
27595
|
+
_proto.onMediaSeeked = function onMediaSeeked() {
|
27596
|
+
var media = this.media;
|
27597
|
+
var currentTime = media ? media.currentTime : null;
|
27598
|
+
if (isFiniteNumber(currentTime)) {
|
27599
|
+
this.log("Media seeked to " + currentTime.toFixed(3));
|
27600
|
+
}
|
27601
|
+
|
27602
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
27603
|
+
var bufferInfo = this.getMainFwdBufferInfo();
|
27604
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
27605
|
+
this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27606
|
+
return;
|
27607
|
+
}
|
27608
|
+
|
27609
|
+
// tick to speed up FRAG_CHANGED triggering
|
27610
|
+
this.tick();
|
27611
|
+
};
|
28520
27612
|
_proto.onManifestLoading = function onManifestLoading() {
|
28521
27613
|
// reset buffer on manifest loading
|
28522
27614
|
this.log('Trigger BUFFER_RESET');
|
@@ -28797,10 +27889,8 @@
|
|
28797
27889
|
}
|
28798
27890
|
if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
|
28799
27891
|
// Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
|
28800
|
-
var
|
28801
|
-
|
28802
|
-
var levelDetails = this.getLevelDetails();
|
28803
|
-
gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
|
27892
|
+
var activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;
|
27893
|
+
gapController.poll(this.lastCurrentTime, activeFrag);
|
28804
27894
|
}
|
28805
27895
|
this.lastCurrentTime = media.currentTime;
|
28806
27896
|
};
|
@@ -29265,12 +28355,9 @@
|
|
29265
28355
|
* The configuration object provided on player instantiation.
|
29266
28356
|
*/
|
29267
28357
|
this.userConfig = void 0;
|
29268
|
-
/**
|
29269
|
-
* The logger functions used by this player instance, configured on player instantiation.
|
29270
|
-
*/
|
29271
|
-
this.logger = void 0;
|
29272
28358
|
this.coreComponents = void 0;
|
29273
28359
|
this.networkControllers = void 0;
|
28360
|
+
this.started = false;
|
29274
28361
|
this._emitter = new EventEmitter();
|
29275
28362
|
this._autoLevelCapping = -1;
|
29276
28363
|
this._maxHdcpLevel = null;
|
@@ -29287,11 +28374,11 @@
|
|
29287
28374
|
this._media = null;
|
29288
28375
|
this.url = null;
|
29289
28376
|
this.triggeringException = void 0;
|
29290
|
-
|
29291
|
-
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig
|
28377
|
+
enableLogs(userConfig.debug || false, 'Hls instance');
|
28378
|
+
var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
|
29292
28379
|
this.userConfig = userConfig;
|
29293
28380
|
if (config.progressive) {
|
29294
|
-
enableStreamingMode(config
|
28381
|
+
enableStreamingMode(config);
|
29295
28382
|
}
|
29296
28383
|
|
29297
28384
|
// core controllers and network loaders
|
@@ -29399,7 +28486,7 @@
|
|
29399
28486
|
try {
|
29400
28487
|
return this.emit(event, event, eventObject);
|
29401
28488
|
} catch (error) {
|
29402
|
-
|
28489
|
+
logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
|
29403
28490
|
// Prevent recursion in error event handlers that throw #5497
|
29404
28491
|
if (!this.triggeringException) {
|
29405
28492
|
this.triggeringException = true;
|
@@ -29425,7 +28512,7 @@
|
|
29425
28512
|
* Dispose of the instance
|
29426
28513
|
*/;
|
29427
28514
|
_proto.destroy = function destroy() {
|
29428
|
-
|
28515
|
+
logger.log('destroy');
|
29429
28516
|
this.trigger(Events.DESTROYING, undefined);
|
29430
28517
|
this.detachMedia();
|
29431
28518
|
this.removeAllListeners();
|
@@ -29450,7 +28537,7 @@
|
|
29450
28537
|
* Attaches Hls.js to a media element
|
29451
28538
|
*/;
|
29452
28539
|
_proto.attachMedia = function attachMedia(media) {
|
29453
|
-
|
28540
|
+
logger.log('attachMedia');
|
29454
28541
|
this._media = media;
|
29455
28542
|
this.trigger(Events.MEDIA_ATTACHING, {
|
29456
28543
|
media: media
|
@@ -29461,7 +28548,7 @@
|
|
29461
28548
|
* Detach Hls.js from the media
|
29462
28549
|
*/;
|
29463
28550
|
_proto.detachMedia = function detachMedia() {
|
29464
|
-
|
28551
|
+
logger.log('detachMedia');
|
29465
28552
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
29466
28553
|
this._media = null;
|
29467
28554
|
}
|
@@ -29478,7 +28565,7 @@
|
|
29478
28565
|
});
|
29479
28566
|
this._autoLevelCapping = -1;
|
29480
28567
|
this._maxHdcpLevel = null;
|
29481
|
-
|
28568
|
+
logger.log("loadSource:" + loadingSource);
|
29482
28569
|
if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
|
29483
28570
|
this.detachMedia();
|
29484
28571
|
this.attachMedia(media);
|
@@ -29500,7 +28587,8 @@
|
|
29500
28587
|
if (startPosition === void 0) {
|
29501
28588
|
startPosition = -1;
|
29502
28589
|
}
|
29503
|
-
|
28590
|
+
logger.log("startLoad(" + startPosition + ")");
|
28591
|
+
this.started = true;
|
29504
28592
|
this.networkControllers.forEach(function (controller) {
|
29505
28593
|
controller.startLoad(startPosition);
|
29506
28594
|
});
|
@@ -29510,31 +28598,34 @@
|
|
29510
28598
|
* Stop loading of any stream data.
|
29511
28599
|
*/;
|
29512
28600
|
_proto.stopLoad = function stopLoad() {
|
29513
|
-
|
28601
|
+
logger.log('stopLoad');
|
28602
|
+
this.started = false;
|
29514
28603
|
this.networkControllers.forEach(function (controller) {
|
29515
28604
|
controller.stopLoad();
|
29516
28605
|
});
|
29517
28606
|
}
|
29518
28607
|
|
29519
28608
|
/**
|
29520
|
-
* Resumes stream controller segment loading
|
28609
|
+
* Resumes stream controller segment loading if previously started.
|
29521
28610
|
*/;
|
29522
28611
|
_proto.resumeBuffering = function resumeBuffering() {
|
29523
|
-
this.
|
29524
|
-
|
29525
|
-
controller
|
29526
|
-
|
29527
|
-
|
28612
|
+
if (this.started) {
|
28613
|
+
this.networkControllers.forEach(function (controller) {
|
28614
|
+
if ('fragmentLoader' in controller) {
|
28615
|
+
controller.startLoad(-1);
|
28616
|
+
}
|
28617
|
+
});
|
28618
|
+
}
|
29528
28619
|
}
|
29529
28620
|
|
29530
28621
|
/**
|
29531
|
-
*
|
28622
|
+
* Stops stream controller segment loading without changing 'started' state like stopLoad().
|
29532
28623
|
* This allows for media buffering to be paused without interupting playlist loading.
|
29533
28624
|
*/;
|
29534
28625
|
_proto.pauseBuffering = function pauseBuffering() {
|
29535
28626
|
this.networkControllers.forEach(function (controller) {
|
29536
|
-
if (controller
|
29537
|
-
controller.
|
28627
|
+
if ('fragmentLoader' in controller) {
|
28628
|
+
controller.stopLoad();
|
29538
28629
|
}
|
29539
28630
|
});
|
29540
28631
|
}
|
@@ -29543,7 +28634,7 @@
|
|
29543
28634
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
29544
28635
|
*/;
|
29545
28636
|
_proto.swapAudioCodec = function swapAudioCodec() {
|
29546
|
-
|
28637
|
+
logger.log('swapAudioCodec');
|
29547
28638
|
this.streamController.swapAudioCodec();
|
29548
28639
|
}
|
29549
28640
|
|
@@ -29554,7 +28645,7 @@
|
|
29554
28645
|
* Automatic recovery of media-errors by this process is configurable.
|
29555
28646
|
*/;
|
29556
28647
|
_proto.recoverMediaError = function recoverMediaError() {
|
29557
|
-
|
28648
|
+
logger.log('recoverMediaError');
|
29558
28649
|
var media = this._media;
|
29559
28650
|
this.detachMedia();
|
29560
28651
|
if (media) {
|
@@ -29609,7 +28700,7 @@
|
|
29609
28700
|
* 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.
|
29610
28701
|
*/,
|
29611
28702
|
set: function set(newLevel) {
|
29612
|
-
|
28703
|
+
logger.log("set currentLevel:" + newLevel);
|
29613
28704
|
this.levelController.manualLevel = newLevel;
|
29614
28705
|
this.streamController.immediateLevelSwitch();
|
29615
28706
|
}
|
@@ -29630,7 +28721,7 @@
|
|
29630
28721
|
* @param newLevel - Pass -1 for automatic level selection
|
29631
28722
|
*/,
|
29632
28723
|
set: function set(newLevel) {
|
29633
|
-
|
28724
|
+
logger.log("set nextLevel:" + newLevel);
|
29634
28725
|
this.levelController.manualLevel = newLevel;
|
29635
28726
|
this.streamController.nextLevelSwitch();
|
29636
28727
|
}
|
@@ -29651,7 +28742,7 @@
|
|
29651
28742
|
* @param newLevel - Pass -1 for automatic level selection
|
29652
28743
|
*/,
|
29653
28744
|
set: function set(newLevel) {
|
29654
|
-
|
28745
|
+
logger.log("set loadLevel:" + newLevel);
|
29655
28746
|
this.levelController.manualLevel = newLevel;
|
29656
28747
|
}
|
29657
28748
|
|
@@ -29686,7 +28777,7 @@
|
|
29686
28777
|
* Sets "first-level", see getter.
|
29687
28778
|
*/,
|
29688
28779
|
set: function set(newLevel) {
|
29689
|
-
|
28780
|
+
logger.log("set firstLevel:" + newLevel);
|
29690
28781
|
this.levelController.firstLevel = newLevel;
|
29691
28782
|
}
|
29692
28783
|
|
@@ -29713,7 +28804,7 @@
|
|
29713
28804
|
* (determined from download of first segment)
|
29714
28805
|
*/,
|
29715
28806
|
set: function set(newLevel) {
|
29716
|
-
|
28807
|
+
logger.log("set startLevel:" + newLevel);
|
29717
28808
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
29718
28809
|
if (newLevel !== -1) {
|
29719
28810
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -29766,7 +28857,7 @@
|
|
29766
28857
|
*/
|
29767
28858
|
function set(newLevel) {
|
29768
28859
|
if (this._autoLevelCapping !== newLevel) {
|
29769
|
-
|
28860
|
+
logger.log("set autoLevelCapping:" + newLevel);
|
29770
28861
|
this._autoLevelCapping = newLevel;
|
29771
28862
|
this.levelController.checkMaxAutoUpdated();
|
29772
28863
|
}
|
@@ -30091,7 +29182,7 @@
|
|
30091
29182
|
* Get the video-dev/hls.js package version.
|
30092
29183
|
*/
|
30093
29184
|
function get() {
|
30094
|
-
return "1.5.5
|
29185
|
+
return "1.5.5";
|
30095
29186
|
}
|
30096
29187
|
}, {
|
30097
29188
|
key: "Events",
|