hls.js 1.5.2-0.canary.9923 → 1.5.2
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/dist/hls-demo.js +0 -5
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +379 -431
- package/dist/hls.js.d.ts +14 -14
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +217 -275
- 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 +219 -278
- 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 +350 -401
- 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 +9 -9
- package/src/controller/abr-controller.ts +2 -2
- package/src/controller/base-stream-controller.ts +16 -16
- package/src/controller/buffer-controller.ts +0 -6
- package/src/controller/eme-controller.ts +12 -6
- package/src/controller/latency-controller.ts +8 -7
- package/src/controller/level-controller.ts +18 -7
- package/src/controller/stream-controller.ts +14 -11
- package/src/controller/subtitle-stream-controller.ts +1 -6
- package/src/controller/subtitle-track-controller.ts +2 -4
- package/src/controller/timeline-controller.ts +26 -20
- 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.ts +3 -16
- package/src/demux/tsdemuxer.ts +17 -12
- 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/remux/mp4-remuxer.ts +3 -4
- package/src/types/demuxer.ts +0 -1
- package/src/utils/codecs.ts +4 -33
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/utils/encryption-methods-util.ts +0 -21
package/dist/hls.light.js
CHANGED
@@ -521,7 +521,7 @@
|
|
521
521
|
// Some browsers don't allow to use bind on console object anyway
|
522
522
|
// fallback to default if needed
|
523
523
|
try {
|
524
|
-
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.2
|
524
|
+
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.2");
|
525
525
|
} catch (e) {
|
526
526
|
exportedLogger = fakeLogger;
|
527
527
|
}
|
@@ -1173,26 +1173,6 @@
|
|
1173
1173
|
return LevelDetails;
|
1174
1174
|
}();
|
1175
1175
|
|
1176
|
-
var DecrypterAesMode = {
|
1177
|
-
cbc: 0,
|
1178
|
-
ctr: 1
|
1179
|
-
};
|
1180
|
-
|
1181
|
-
function isFullSegmentEncryption(method) {
|
1182
|
-
return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
|
1183
|
-
}
|
1184
|
-
function getAesModeFromFullSegmentMethod(method) {
|
1185
|
-
switch (method) {
|
1186
|
-
case 'AES-128':
|
1187
|
-
case 'AES-256':
|
1188
|
-
return DecrypterAesMode.cbc;
|
1189
|
-
case 'AES-256-CTR':
|
1190
|
-
return DecrypterAesMode.ctr;
|
1191
|
-
default:
|
1192
|
-
throw new Error("invalid full segment method " + method);
|
1193
|
-
}
|
1194
|
-
}
|
1195
|
-
|
1196
1176
|
// This file is inserted as a shim for modules which we do not want to include into the distro.
|
1197
1177
|
// This replacement is done in the "alias" plugin of the rollup config.
|
1198
1178
|
var empty = undefined;
|
@@ -2634,13 +2614,13 @@
|
|
2634
2614
|
this.keyFormatVersions = formatversions;
|
2635
2615
|
this.iv = iv;
|
2636
2616
|
this.encrypted = method ? method !== 'NONE' : false;
|
2637
|
-
this.isCommonEncryption = this.encrypted &&
|
2617
|
+
this.isCommonEncryption = this.encrypted && method !== 'AES-128';
|
2638
2618
|
}
|
2639
2619
|
var _proto = LevelKey.prototype;
|
2640
2620
|
_proto.isSupported = function isSupported() {
|
2641
2621
|
// If it's Segment encryption or No encryption, just select that key system
|
2642
2622
|
if (this.method) {
|
2643
|
-
if (
|
2623
|
+
if (this.method === 'AES-128' || this.method === 'NONE') {
|
2644
2624
|
return true;
|
2645
2625
|
}
|
2646
2626
|
if (this.keyFormat === 'identity') {
|
@@ -2654,13 +2634,14 @@
|
|
2654
2634
|
if (!this.encrypted || !this.uri) {
|
2655
2635
|
return null;
|
2656
2636
|
}
|
2657
|
-
if (
|
2637
|
+
if (this.method === 'AES-128' && this.uri && !this.iv) {
|
2658
2638
|
if (typeof sn !== 'number') {
|
2659
2639
|
// We are fetching decryption data for a initialization segment
|
2660
|
-
// If the segment was encrypted with AES-128
|
2640
|
+
// If the segment was encrypted with AES-128
|
2661
2641
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
2662
|
-
|
2663
|
-
|
2642
|
+
if (this.method === 'AES-128' && !this.iv) {
|
2643
|
+
logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
|
2644
|
+
}
|
2664
2645
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
2665
2646
|
sn = 0;
|
2666
2647
|
}
|
@@ -2822,28 +2803,23 @@
|
|
2822
2803
|
if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
|
2823
2804
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
|
2824
2805
|
}
|
2806
|
+
|
2807
|
+
// Idealy fLaC and Opus would be first (spec-compliant) but
|
2808
|
+
// some browsers will report that fLaC is supported then fail.
|
2809
|
+
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
2825
2810
|
var codecsToCheck = {
|
2826
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
2827
|
-
// some browsers will report that fLaC is supported then fail.
|
2828
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
2829
2811
|
flac: ['flac', 'fLaC', 'FLAC'],
|
2830
|
-
opus: ['opus', 'Opus']
|
2831
|
-
// Replace audio codec info if browser does not support mp4a.40.34,
|
2832
|
-
// and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
|
2833
|
-
'mp4a.40.34': ['mp3']
|
2812
|
+
opus: ['opus', 'Opus']
|
2834
2813
|
}[lowerCaseCodec];
|
2835
2814
|
for (var i = 0; i < codecsToCheck.length; i++) {
|
2836
|
-
var _getMediaSource;
|
2837
2815
|
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
|
2838
2816
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
2839
2817
|
return codecsToCheck[i];
|
2840
|
-
} else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
|
2841
|
-
return '';
|
2842
2818
|
}
|
2843
2819
|
}
|
2844
2820
|
return lowerCaseCodec;
|
2845
2821
|
}
|
2846
|
-
var AUDIO_CODEC_REGEXP = /flac|opus
|
2822
|
+
var AUDIO_CODEC_REGEXP = /flac|opus/i;
|
2847
2823
|
function getCodecCompatibleName(codec, preferManagedMediaSource) {
|
2848
2824
|
if (preferManagedMediaSource === void 0) {
|
2849
2825
|
preferManagedMediaSource = true;
|
@@ -2871,18 +2847,6 @@
|
|
2871
2847
|
}
|
2872
2848
|
return codec;
|
2873
2849
|
}
|
2874
|
-
function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
|
2875
|
-
var MediaSource = getMediaSource(preferManagedMediaSource) || {
|
2876
|
-
isTypeSupported: function isTypeSupported() {
|
2877
|
-
return false;
|
2878
|
-
}
|
2879
|
-
};
|
2880
|
-
return {
|
2881
|
-
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
2882
|
-
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
2883
|
-
ac3: false
|
2884
|
-
};
|
2885
|
-
}
|
2886
2850
|
|
2887
2851
|
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;
|
2888
2852
|
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
|
@@ -4457,43 +4421,8 @@
|
|
4457
4421
|
this.currentTime = 0;
|
4458
4422
|
this.stallCount = 0;
|
4459
4423
|
this._latency = null;
|
4460
|
-
this.
|
4461
|
-
|
4462
|
-
levelDetails = _this.levelDetails;
|
4463
|
-
if (!media || !levelDetails) {
|
4464
|
-
return;
|
4465
|
-
}
|
4466
|
-
_this.currentTime = media.currentTime;
|
4467
|
-
var latency = _this.computeLatency();
|
4468
|
-
if (latency === null) {
|
4469
|
-
return;
|
4470
|
-
}
|
4471
|
-
_this._latency = latency;
|
4472
|
-
|
4473
|
-
// Adapt playbackRate to meet target latency in low-latency mode
|
4474
|
-
var _this$config = _this.config,
|
4475
|
-
lowLatencyMode = _this$config.lowLatencyMode,
|
4476
|
-
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
4477
|
-
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
4478
|
-
return;
|
4479
|
-
}
|
4480
|
-
var targetLatency = _this.targetLatency;
|
4481
|
-
if (targetLatency === null) {
|
4482
|
-
return;
|
4483
|
-
}
|
4484
|
-
var distanceFromTarget = latency - targetLatency;
|
4485
|
-
// Only adjust playbackRate when within one target duration of targetLatency
|
4486
|
-
// and more than one second from under-buffering.
|
4487
|
-
// Playback further than one target duration from target can be considered DVR playback.
|
4488
|
-
var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
|
4489
|
-
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
4490
|
-
if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
|
4491
|
-
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
4492
|
-
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
|
4493
|
-
media.playbackRate = Math.min(max, Math.max(1, rate));
|
4494
|
-
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
4495
|
-
media.playbackRate = 1;
|
4496
|
-
}
|
4424
|
+
this.timeupdateHandler = function () {
|
4425
|
+
return _this.timeupdate();
|
4497
4426
|
};
|
4498
4427
|
this.hls = hls;
|
4499
4428
|
this.config = hls.config;
|
@@ -4505,7 +4434,7 @@
|
|
4505
4434
|
this.onMediaDetaching();
|
4506
4435
|
this.levelDetails = null;
|
4507
4436
|
// @ts-ignore
|
4508
|
-
this.hls = this.
|
4437
|
+
this.hls = this.timeupdateHandler = null;
|
4509
4438
|
};
|
4510
4439
|
_proto.registerListeners = function registerListeners() {
|
4511
4440
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -4523,11 +4452,11 @@
|
|
4523
4452
|
};
|
4524
4453
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
4525
4454
|
this.media = data.media;
|
4526
|
-
this.media.addEventListener('timeupdate', this.
|
4455
|
+
this.media.addEventListener('timeupdate', this.timeupdateHandler);
|
4527
4456
|
};
|
4528
4457
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
4529
4458
|
if (this.media) {
|
4530
|
-
this.media.removeEventListener('timeupdate', this.
|
4459
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
4531
4460
|
this.media = null;
|
4532
4461
|
}
|
4533
4462
|
};
|
@@ -4540,10 +4469,10 @@
|
|
4540
4469
|
var details = _ref.details;
|
4541
4470
|
this.levelDetails = details;
|
4542
4471
|
if (details.advanced) {
|
4543
|
-
this.
|
4472
|
+
this.timeupdate();
|
4544
4473
|
}
|
4545
4474
|
if (!details.live && this.media) {
|
4546
|
-
this.media.removeEventListener('timeupdate', this.
|
4475
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
4547
4476
|
}
|
4548
4477
|
};
|
4549
4478
|
_proto.onError = function onError(event, data) {
|
@@ -4556,6 +4485,44 @@
|
|
4556
4485
|
logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
|
4557
4486
|
}
|
4558
4487
|
};
|
4488
|
+
_proto.timeupdate = function timeupdate() {
|
4489
|
+
var media = this.media,
|
4490
|
+
levelDetails = this.levelDetails;
|
4491
|
+
if (!media || !levelDetails) {
|
4492
|
+
return;
|
4493
|
+
}
|
4494
|
+
this.currentTime = media.currentTime;
|
4495
|
+
var latency = this.computeLatency();
|
4496
|
+
if (latency === null) {
|
4497
|
+
return;
|
4498
|
+
}
|
4499
|
+
this._latency = latency;
|
4500
|
+
|
4501
|
+
// Adapt playbackRate to meet target latency in low-latency mode
|
4502
|
+
var _this$config = this.config,
|
4503
|
+
lowLatencyMode = _this$config.lowLatencyMode,
|
4504
|
+
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
4505
|
+
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
4506
|
+
return;
|
4507
|
+
}
|
4508
|
+
var targetLatency = this.targetLatency;
|
4509
|
+
if (targetLatency === null) {
|
4510
|
+
return;
|
4511
|
+
}
|
4512
|
+
var distanceFromTarget = latency - targetLatency;
|
4513
|
+
// Only adjust playbackRate when within one target duration of targetLatency
|
4514
|
+
// and more than one second from under-buffering.
|
4515
|
+
// Playback further than one target duration from target can be considered DVR playback.
|
4516
|
+
var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
|
4517
|
+
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
4518
|
+
if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
|
4519
|
+
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
4520
|
+
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
|
4521
|
+
media.playbackRate = Math.min(max, Math.max(1, rate));
|
4522
|
+
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
4523
|
+
media.playbackRate = 1;
|
4524
|
+
}
|
4525
|
+
};
|
4559
4526
|
_proto.estimateLiveEdge = function estimateLiveEdge() {
|
4560
4527
|
var levelDetails = this.levelDetails;
|
4561
4528
|
if (levelDetails === null) {
|
@@ -6507,7 +6474,7 @@
|
|
6507
6474
|
var bwEstimate = _this.getBwEstimate();
|
6508
6475
|
var levels = hls.levels;
|
6509
6476
|
var level = levels[frag.level];
|
6510
|
-
var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.
|
6477
|
+
var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.averageBitrate / 8));
|
6511
6478
|
var timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
|
6512
6479
|
if (timeStreaming < 1 && loadedFirstByte) {
|
6513
6480
|
timeStreaming = Math.min(timeLoading, stats.loaded * 8 / bwEstimate);
|
@@ -6550,7 +6517,7 @@
|
|
6550
6517
|
// If there has been no loading progress, sample TTFB
|
6551
6518
|
_this.bwEstimator.sampleTTFB(timeLoading);
|
6552
6519
|
}
|
6553
|
-
var nextLoadLevelBitrate = levels[nextLoadLevel].
|
6520
|
+
var nextLoadLevelBitrate = levels[nextLoadLevel].maxBitrate;
|
6554
6521
|
if (_this.getBwEstimate() * _this.hls.config.abrBandWidthUpFactor > nextLoadLevelBitrate) {
|
6555
6522
|
_this.resetEstimator(nextLoadLevelBitrate);
|
6556
6523
|
}
|
@@ -7341,12 +7308,6 @@
|
|
7341
7308
|
this.lastMpegAudioChunk = null;
|
7342
7309
|
// @ts-ignore
|
7343
7310
|
this.hls = null;
|
7344
|
-
// @ts-ignore
|
7345
|
-
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
7346
|
-
// @ts-ignore
|
7347
|
-
this._onMediaSourceEnded = null;
|
7348
|
-
// @ts-ignore
|
7349
|
-
this._onStartStreaming = this._onEndStreaming = null;
|
7350
7311
|
};
|
7351
7312
|
_proto.registerListeners = function registerListeners() {
|
7352
7313
|
var hls = this.hls;
|
@@ -9905,6 +9866,7 @@
|
|
9905
9866
|
}
|
9906
9867
|
}
|
9907
9868
|
|
9869
|
+
var chromeOrFirefox;
|
9908
9870
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
9909
9871
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
9910
9872
|
function LevelController(hls, contentSteeringController) {
|
@@ -9978,13 +9940,21 @@
|
|
9978
9940
|
var videoCodecFound = false;
|
9979
9941
|
var audioCodecFound = false;
|
9980
9942
|
data.levels.forEach(function (levelParsed) {
|
9981
|
-
var _videoCodec;
|
9943
|
+
var _audioCodec, _videoCodec;
|
9982
9944
|
var attributes = levelParsed.attrs;
|
9945
|
+
|
9946
|
+
// erase audio codec info if browser does not support mp4a.40.34.
|
9947
|
+
// demuxer will autodetect codec and fallback to mpeg/audio
|
9983
9948
|
var audioCodec = levelParsed.audioCodec,
|
9984
9949
|
videoCodec = levelParsed.videoCodec;
|
9950
|
+
if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
|
9951
|
+
chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
|
9952
|
+
if (chromeOrFirefox) {
|
9953
|
+
levelParsed.audioCodec = audioCodec = undefined;
|
9954
|
+
}
|
9955
|
+
}
|
9985
9956
|
if (audioCodec) {
|
9986
|
-
|
9987
|
-
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
9957
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
|
9988
9958
|
}
|
9989
9959
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
9990
9960
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -10107,8 +10077,8 @@
|
|
10107
10077
|
return _valueB - _valueA;
|
10108
10078
|
}
|
10109
10079
|
}
|
10110
|
-
if (a.
|
10111
|
-
return a.
|
10080
|
+
if (a.averageBitrate !== b.averageBitrate) {
|
10081
|
+
return a.averageBitrate - b.averageBitrate;
|
10112
10082
|
}
|
10113
10083
|
return 0;
|
10114
10084
|
});
|
@@ -11131,8 +11101,8 @@
|
|
11131
11101
|
var _frag$decryptdata;
|
11132
11102
|
var byteRangeStart = start;
|
11133
11103
|
var byteRangeEnd = end;
|
11134
|
-
if (frag.sn === 'initSegment' &&
|
11135
|
-
// MAP segment encrypted with method 'AES-128'
|
11104
|
+
if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
|
11105
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
11136
11106
|
// has the unencrypted size specified in the range.
|
11137
11107
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
11138
11108
|
var fragmentLen = end - start;
|
@@ -11165,9 +11135,6 @@
|
|
11165
11135
|
(part ? part : frag).stats.aborted = true;
|
11166
11136
|
return new LoadError(errorData);
|
11167
11137
|
}
|
11168
|
-
function isMethodFullSegmentAesCbc(method) {
|
11169
|
-
return method === 'AES-128' || method === 'AES-256';
|
11170
|
-
}
|
11171
11138
|
var LoadError = /*#__PURE__*/function (_Error) {
|
11172
11139
|
_inheritsLoose(LoadError, _Error);
|
11173
11140
|
function LoadError(data) {
|
@@ -11324,8 +11291,6 @@
|
|
11324
11291
|
}
|
11325
11292
|
return this.loadKeyEME(keyInfo, frag);
|
11326
11293
|
case 'AES-128':
|
11327
|
-
case 'AES-256':
|
11328
|
-
case 'AES-256-CTR':
|
11329
11294
|
return this.loadKeyHTTP(keyInfo, frag);
|
11330
11295
|
default:
|
11331
11296
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -11737,65 +11702,37 @@
|
|
11737
11702
|
}
|
11738
11703
|
|
11739
11704
|
var AESCrypto = /*#__PURE__*/function () {
|
11740
|
-
function AESCrypto(subtle, iv
|
11705
|
+
function AESCrypto(subtle, iv) {
|
11741
11706
|
this.subtle = void 0;
|
11742
11707
|
this.aesIV = void 0;
|
11743
|
-
this.aesMode = void 0;
|
11744
11708
|
this.subtle = subtle;
|
11745
11709
|
this.aesIV = iv;
|
11746
|
-
this.aesMode = aesMode;
|
11747
11710
|
}
|
11748
11711
|
var _proto = AESCrypto.prototype;
|
11749
11712
|
_proto.decrypt = function decrypt(data, key) {
|
11750
|
-
|
11751
|
-
|
11752
|
-
|
11753
|
-
|
11754
|
-
iv: this.aesIV
|
11755
|
-
}, key, data);
|
11756
|
-
case DecrypterAesMode.ctr:
|
11757
|
-
return this.subtle.decrypt({
|
11758
|
-
name: 'AES-CTR',
|
11759
|
-
counter: this.aesIV,
|
11760
|
-
length: 64
|
11761
|
-
},
|
11762
|
-
//64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
|
11763
|
-
key, data);
|
11764
|
-
default:
|
11765
|
-
throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
|
11766
|
-
}
|
11713
|
+
return this.subtle.decrypt({
|
11714
|
+
name: 'AES-CBC',
|
11715
|
+
iv: this.aesIV
|
11716
|
+
}, key, data);
|
11767
11717
|
};
|
11768
11718
|
return AESCrypto;
|
11769
11719
|
}();
|
11770
11720
|
|
11771
11721
|
var FastAESKey = /*#__PURE__*/function () {
|
11772
|
-
function FastAESKey(subtle, key
|
11722
|
+
function FastAESKey(subtle, key) {
|
11773
11723
|
this.subtle = void 0;
|
11774
11724
|
this.key = void 0;
|
11775
|
-
this.aesMode = void 0;
|
11776
11725
|
this.subtle = subtle;
|
11777
11726
|
this.key = key;
|
11778
|
-
this.aesMode = aesMode;
|
11779
11727
|
}
|
11780
11728
|
var _proto = FastAESKey.prototype;
|
11781
11729
|
_proto.expandKey = function expandKey() {
|
11782
|
-
var subtleAlgoName = getSubtleAlgoName(this.aesMode);
|
11783
11730
|
return this.subtle.importKey('raw', this.key, {
|
11784
|
-
name:
|
11731
|
+
name: 'AES-CBC'
|
11785
11732
|
}, false, ['encrypt', 'decrypt']);
|
11786
11733
|
};
|
11787
11734
|
return FastAESKey;
|
11788
11735
|
}();
|
11789
|
-
function getSubtleAlgoName(aesMode) {
|
11790
|
-
switch (aesMode) {
|
11791
|
-
case DecrypterAesMode.cbc:
|
11792
|
-
return 'AES-CBC';
|
11793
|
-
case DecrypterAesMode.ctr:
|
11794
|
-
return 'AES-CTR';
|
11795
|
-
default:
|
11796
|
-
throw new Error("[FastAESKey] invalid aes mode " + aesMode);
|
11797
|
-
}
|
11798
|
-
}
|
11799
11736
|
|
11800
11737
|
// PKCS7
|
11801
11738
|
function removePadding(array) {
|
@@ -12048,8 +11985,7 @@
|
|
12048
11985
|
this.currentIV = null;
|
12049
11986
|
this.currentResult = null;
|
12050
11987
|
this.useSoftware = void 0;
|
12051
|
-
this.
|
12052
|
-
this.enableSoftwareAES = config.enableSoftwareAES;
|
11988
|
+
this.useSoftware = config.enableSoftwareAES;
|
12053
11989
|
this.removePKCS7Padding = removePKCS7Padding;
|
12054
11990
|
// built in decryptor expects PKCS7 padding
|
12055
11991
|
if (removePKCS7Padding) {
|
@@ -12062,7 +11998,9 @@
|
|
12062
11998
|
/* no-op */
|
12063
11999
|
}
|
12064
12000
|
}
|
12065
|
-
|
12001
|
+
if (this.subtle === null) {
|
12002
|
+
this.useSoftware = true;
|
12003
|
+
}
|
12066
12004
|
}
|
12067
12005
|
var _proto = Decrypter.prototype;
|
12068
12006
|
_proto.destroy = function destroy() {
|
@@ -12099,11 +12037,11 @@
|
|
12099
12037
|
this.softwareDecrypter = null;
|
12100
12038
|
}
|
12101
12039
|
};
|
12102
|
-
_proto.decrypt = function decrypt(data, key, iv
|
12040
|
+
_proto.decrypt = function decrypt(data, key, iv) {
|
12103
12041
|
var _this = this;
|
12104
12042
|
if (this.useSoftware) {
|
12105
12043
|
return new Promise(function (resolve, reject) {
|
12106
|
-
_this.softwareDecrypt(new Uint8Array(data), key, iv
|
12044
|
+
_this.softwareDecrypt(new Uint8Array(data), key, iv);
|
12107
12045
|
var decryptResult = _this.flush();
|
12108
12046
|
if (decryptResult) {
|
12109
12047
|
resolve(decryptResult.buffer);
|
@@ -12112,20 +12050,16 @@
|
|
12112
12050
|
}
|
12113
12051
|
});
|
12114
12052
|
}
|
12115
|
-
return this.webCryptoDecrypt(new Uint8Array(data), key, iv
|
12053
|
+
return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
|
12116
12054
|
}
|
12117
12055
|
|
12118
12056
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
12119
12057
|
// data is handled in the flush() call
|
12120
12058
|
;
|
12121
|
-
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv
|
12059
|
+
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
|
12122
12060
|
var currentIV = this.currentIV,
|
12123
12061
|
currentResult = this.currentResult,
|
12124
12062
|
remainderData = this.remainderData;
|
12125
|
-
if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
|
12126
|
-
logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
|
12127
|
-
return null;
|
12128
|
-
}
|
12129
12063
|
this.logOnce('JS AES decrypt');
|
12130
12064
|
// The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
|
12131
12065
|
// This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
|
@@ -12158,12 +12092,12 @@
|
|
12158
12092
|
}
|
12159
12093
|
return result;
|
12160
12094
|
};
|
12161
|
-
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv
|
12095
|
+
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
|
12162
12096
|
var _this2 = this;
|
12163
12097
|
var subtle = this.subtle;
|
12164
12098
|
if (this.key !== key || !this.fastAesKey) {
|
12165
12099
|
this.key = key;
|
12166
|
-
this.fastAesKey = new FastAESKey(subtle, key
|
12100
|
+
this.fastAesKey = new FastAESKey(subtle, key);
|
12167
12101
|
}
|
12168
12102
|
return this.fastAesKey.expandKey().then(function (aesKey) {
|
12169
12103
|
// decrypt using web crypto
|
@@ -12171,25 +12105,22 @@
|
|
12171
12105
|
return Promise.reject(new Error('web crypto not initialized'));
|
12172
12106
|
}
|
12173
12107
|
_this2.logOnce('WebCrypto AES decrypt');
|
12174
|
-
var crypto = new AESCrypto(subtle, new Uint8Array(iv)
|
12108
|
+
var crypto = new AESCrypto(subtle, new Uint8Array(iv));
|
12175
12109
|
return crypto.decrypt(data.buffer, aesKey);
|
12176
12110
|
}).catch(function (err) {
|
12177
12111
|
logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
|
12178
|
-
return _this2.onWebCryptoError(data, key, iv
|
12112
|
+
return _this2.onWebCryptoError(data, key, iv);
|
12179
12113
|
});
|
12180
12114
|
};
|
12181
|
-
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv
|
12182
|
-
|
12183
|
-
|
12184
|
-
|
12185
|
-
|
12186
|
-
|
12187
|
-
|
12188
|
-
if (decryptResult) {
|
12189
|
-
return decryptResult.buffer;
|
12190
|
-
}
|
12115
|
+
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
|
12116
|
+
this.useSoftware = true;
|
12117
|
+
this.logEnabled = true;
|
12118
|
+
this.softwareDecrypt(data, key, iv);
|
12119
|
+
var decryptResult = this.flush();
|
12120
|
+
if (decryptResult) {
|
12121
|
+
return decryptResult.buffer;
|
12191
12122
|
}
|
12192
|
-
throw new Error('WebCrypto
|
12123
|
+
throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
|
12193
12124
|
};
|
12194
12125
|
_proto.getValidChunk = function getValidChunk(data) {
|
12195
12126
|
var currentChunk = data;
|
@@ -12268,58 +12199,11 @@
|
|
12268
12199
|
_this.startFragRequested = false;
|
12269
12200
|
_this.decrypter = void 0;
|
12270
12201
|
_this.initPTS = [];
|
12202
|
+
_this.onvseeking = null;
|
12203
|
+
_this.onvended = null;
|
12271
12204
|
_this.logPrefix = '';
|
12272
12205
|
_this.log = void 0;
|
12273
12206
|
_this.warn = void 0;
|
12274
|
-
_this.onMediaSeeking = function () {
|
12275
|
-
var _assertThisInitialize = _assertThisInitialized(_this),
|
12276
|
-
config = _assertThisInitialize.config,
|
12277
|
-
fragCurrent = _assertThisInitialize.fragCurrent,
|
12278
|
-
media = _assertThisInitialize.media,
|
12279
|
-
mediaBuffer = _assertThisInitialize.mediaBuffer,
|
12280
|
-
state = _assertThisInitialize.state;
|
12281
|
-
var currentTime = media ? media.currentTime : 0;
|
12282
|
-
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
12283
|
-
_this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
12284
|
-
if (_this.state === State.ENDED) {
|
12285
|
-
_this.resetLoadingState();
|
12286
|
-
} else if (fragCurrent) {
|
12287
|
-
// Seeking while frag load is in progress
|
12288
|
-
var tolerance = config.maxFragLookUpTolerance;
|
12289
|
-
var fragStartOffset = fragCurrent.start - tolerance;
|
12290
|
-
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
12291
|
-
// if seeking out of buffered range or into new one
|
12292
|
-
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
12293
|
-
var pastFragment = currentTime > fragEndOffset;
|
12294
|
-
// if the seek position is outside the current fragment range
|
12295
|
-
if (currentTime < fragStartOffset || pastFragment) {
|
12296
|
-
if (pastFragment && fragCurrent.loader) {
|
12297
|
-
_this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
12298
|
-
fragCurrent.abortRequests();
|
12299
|
-
_this.resetLoadingState();
|
12300
|
-
}
|
12301
|
-
_this.fragPrevious = null;
|
12302
|
-
}
|
12303
|
-
}
|
12304
|
-
}
|
12305
|
-
if (media) {
|
12306
|
-
// Remove gap fragments
|
12307
|
-
_this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
|
12308
|
-
_this.lastCurrentTime = currentTime;
|
12309
|
-
}
|
12310
|
-
|
12311
|
-
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
12312
|
-
if (!_this.loadedmetadata && !bufferInfo.len) {
|
12313
|
-
_this.nextLoadPosition = _this.startPosition = currentTime;
|
12314
|
-
}
|
12315
|
-
|
12316
|
-
// Async tick to speed up processing
|
12317
|
-
_this.tickImmediate();
|
12318
|
-
};
|
12319
|
-
_this.onMediaEnded = function () {
|
12320
|
-
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
12321
|
-
_this.startPosition = _this.lastCurrentTime = 0;
|
12322
|
-
};
|
12323
12207
|
_this.playlistType = playlistType;
|
12324
12208
|
_this.logPrefix = logPrefix;
|
12325
12209
|
_this.log = logger.log.bind(logger, logPrefix + ":");
|
@@ -12387,8 +12271,10 @@
|
|
12387
12271
|
};
|
12388
12272
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
12389
12273
|
var media = this.media = this.mediaBuffer = data.media;
|
12390
|
-
|
12391
|
-
|
12274
|
+
this.onvseeking = this.onMediaSeeking.bind(this);
|
12275
|
+
this.onvended = this.onMediaEnded.bind(this);
|
12276
|
+
media.addEventListener('seeking', this.onvseeking);
|
12277
|
+
media.addEventListener('ended', this.onvended);
|
12392
12278
|
var config = this.config;
|
12393
12279
|
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
|
12394
12280
|
this.startLoad(config.startPosition);
|
@@ -12402,9 +12288,10 @@
|
|
12402
12288
|
}
|
12403
12289
|
|
12404
12290
|
// remove video listeners
|
12405
|
-
if (media) {
|
12406
|
-
media.removeEventListener('seeking', this.
|
12407
|
-
media.removeEventListener('ended', this.
|
12291
|
+
if (media && this.onvseeking && this.onvended) {
|
12292
|
+
media.removeEventListener('seeking', this.onvseeking);
|
12293
|
+
media.removeEventListener('ended', this.onvended);
|
12294
|
+
this.onvseeking = this.onvended = null;
|
12408
12295
|
}
|
12409
12296
|
if (this.keyLoader) {
|
12410
12297
|
this.keyLoader.detach();
|
@@ -12414,6 +12301,54 @@
|
|
12414
12301
|
this.fragmentTracker.removeAllFragments();
|
12415
12302
|
this.stopLoad();
|
12416
12303
|
};
|
12304
|
+
_proto.onMediaSeeking = function onMediaSeeking() {
|
12305
|
+
var config = this.config,
|
12306
|
+
fragCurrent = this.fragCurrent,
|
12307
|
+
media = this.media,
|
12308
|
+
mediaBuffer = this.mediaBuffer,
|
12309
|
+
state = this.state;
|
12310
|
+
var currentTime = media ? media.currentTime : 0;
|
12311
|
+
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
12312
|
+
this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
12313
|
+
if (this.state === State.ENDED) {
|
12314
|
+
this.resetLoadingState();
|
12315
|
+
} else if (fragCurrent) {
|
12316
|
+
// Seeking while frag load is in progress
|
12317
|
+
var tolerance = config.maxFragLookUpTolerance;
|
12318
|
+
var fragStartOffset = fragCurrent.start - tolerance;
|
12319
|
+
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
12320
|
+
// if seeking out of buffered range or into new one
|
12321
|
+
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
12322
|
+
var pastFragment = currentTime > fragEndOffset;
|
12323
|
+
// if the seek position is outside the current fragment range
|
12324
|
+
if (currentTime < fragStartOffset || pastFragment) {
|
12325
|
+
if (pastFragment && fragCurrent.loader) {
|
12326
|
+
this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
12327
|
+
fragCurrent.abortRequests();
|
12328
|
+
this.resetLoadingState();
|
12329
|
+
}
|
12330
|
+
this.fragPrevious = null;
|
12331
|
+
}
|
12332
|
+
}
|
12333
|
+
}
|
12334
|
+
if (media) {
|
12335
|
+
// Remove gap fragments
|
12336
|
+
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
12337
|
+
this.lastCurrentTime = currentTime;
|
12338
|
+
}
|
12339
|
+
|
12340
|
+
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
12341
|
+
if (!this.loadedmetadata && !bufferInfo.len) {
|
12342
|
+
this.nextLoadPosition = this.startPosition = currentTime;
|
12343
|
+
}
|
12344
|
+
|
12345
|
+
// Async tick to speed up processing
|
12346
|
+
this.tickImmediate();
|
12347
|
+
};
|
12348
|
+
_proto.onMediaEnded = function onMediaEnded() {
|
12349
|
+
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
12350
|
+
this.startPosition = this.lastCurrentTime = 0;
|
12351
|
+
};
|
12417
12352
|
_proto.onManifestLoaded = function onManifestLoaded(event, data) {
|
12418
12353
|
this.startTimeOffset = data.startTimeOffset;
|
12419
12354
|
this.initPTS = [];
|
@@ -12423,7 +12358,7 @@
|
|
12423
12358
|
this.stopLoad();
|
12424
12359
|
_TaskLoop.prototype.onHandlerDestroying.call(this);
|
12425
12360
|
// @ts-ignore
|
12426
|
-
this.hls =
|
12361
|
+
this.hls = null;
|
12427
12362
|
};
|
12428
12363
|
_proto.onHandlerDestroyed = function onHandlerDestroyed() {
|
12429
12364
|
this.state = State.STOPPED;
|
@@ -12553,10 +12488,10 @@
|
|
12553
12488
|
var decryptData = frag.decryptdata;
|
12554
12489
|
|
12555
12490
|
// check to see if the payload needs to be decrypted
|
12556
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
12491
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
12557
12492
|
var startTime = self.performance.now();
|
12558
12493
|
// decrypt init segment data
|
12559
|
-
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
12494
|
+
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
12560
12495
|
hls.trigger(Events.ERROR, {
|
12561
12496
|
type: ErrorTypes.MEDIA_ERROR,
|
12562
12497
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -13684,7 +13619,6 @@
|
|
13684
13619
|
*/
|
13685
13620
|
function getAudioConfig(observer, data, offset, audioCodec) {
|
13686
13621
|
var adtsObjectType;
|
13687
|
-
var originalAdtsObjectType;
|
13688
13622
|
var adtsExtensionSamplingIndex;
|
13689
13623
|
var adtsChannelConfig;
|
13690
13624
|
var config;
|
@@ -13692,7 +13626,7 @@
|
|
13692
13626
|
var manifestCodec = audioCodec;
|
13693
13627
|
var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
|
13694
13628
|
// byte 2
|
13695
|
-
adtsObjectType =
|
13629
|
+
adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
13696
13630
|
var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
|
13697
13631
|
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
|
13698
13632
|
var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
|
@@ -13709,8 +13643,8 @@
|
|
13709
13643
|
// byte 3
|
13710
13644
|
adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
|
13711
13645
|
logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
|
13712
|
-
//
|
13713
|
-
if (/firefox
|
13646
|
+
// firefox: freq less than 24kHz = AAC SBR (HE-AAC)
|
13647
|
+
if (/firefox/i.test(userAgent)) {
|
13714
13648
|
if (adtsSamplingIndex >= 6) {
|
13715
13649
|
adtsObjectType = 5;
|
13716
13650
|
config = new Array(4);
|
@@ -13804,7 +13738,6 @@
|
|
13804
13738
|
samplerate: adtsSamplingRates[adtsSamplingIndex],
|
13805
13739
|
channelCount: adtsChannelConfig,
|
13806
13740
|
codec: 'mp4a.40.' + adtsObjectType,
|
13807
|
-
parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
|
13808
13741
|
manifestCodec: manifestCodec
|
13809
13742
|
};
|
13810
13743
|
}
|
@@ -13859,8 +13792,7 @@
|
|
13859
13792
|
track.channelCount = config.channelCount;
|
13860
13793
|
track.codec = config.codec;
|
13861
13794
|
track.manifestCodec = config.manifestCodec;
|
13862
|
-
track.
|
13863
|
-
logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
13795
|
+
logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
13864
13796
|
}
|
13865
13797
|
}
|
13866
13798
|
function getFrameDuration(samplerate) {
|
@@ -14947,7 +14879,7 @@
|
|
14947
14879
|
}
|
14948
14880
|
var _proto = SampleAesDecrypter.prototype;
|
14949
14881
|
_proto.decryptBuffer = function decryptBuffer(encryptedData) {
|
14950
|
-
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer
|
14882
|
+
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
|
14951
14883
|
}
|
14952
14884
|
|
14953
14885
|
// AAC - encrypt all full 16 bytes blocks starting from offset 16
|
@@ -17176,7 +17108,7 @@
|
|
17176
17108
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
17177
17109
|
for (var j = 0; j < missing; j++) {
|
17178
17110
|
var newStamp = Math.max(nextPts, 0);
|
17179
|
-
var fillFrame = AAC.getSilentFrame(track.
|
17111
|
+
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
17180
17112
|
if (!fillFrame) {
|
17181
17113
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
17182
17114
|
fillFrame = sample.unit.subarray();
|
@@ -17304,7 +17236,7 @@
|
|
17304
17236
|
// samples count of this segment's duration
|
17305
17237
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
17306
17238
|
// silent frame
|
17307
|
-
var silentFrame = AAC.getSilentFrame(track.
|
17239
|
+
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
17308
17240
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
17309
17241
|
// Can't remux if we can't generate a silent frame...
|
17310
17242
|
if (!silentFrame) {
|
@@ -17691,15 +17623,13 @@
|
|
17691
17623
|
duration = transmuxConfig.duration,
|
17692
17624
|
initSegmentData = transmuxConfig.initSegmentData;
|
17693
17625
|
var keyData = getEncryptionType(uintData, decryptdata);
|
17694
|
-
if (keyData &&
|
17626
|
+
if (keyData && keyData.method === 'AES-128') {
|
17695
17627
|
var decrypter = this.getDecrypter();
|
17696
|
-
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
17697
|
-
|
17698
17628
|
// Software decryption is synchronous; webCrypto is not
|
17699
17629
|
if (decrypter.isSync()) {
|
17700
17630
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
17701
17631
|
// data is handled in the flush() call
|
17702
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
17632
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
17703
17633
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
17704
17634
|
var loadingParts = chunkMeta.part > -1;
|
17705
17635
|
if (loadingParts) {
|
@@ -17711,7 +17641,7 @@
|
|
17711
17641
|
}
|
17712
17642
|
uintData = new Uint8Array(decryptedData);
|
17713
17643
|
} else {
|
17714
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
17644
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
17715
17645
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
17716
17646
|
// the decrypted data has been transmuxed
|
17717
17647
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -18528,7 +18458,16 @@
|
|
18528
18458
|
this.observer = new EventEmitter();
|
18529
18459
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
18530
18460
|
this.observer.on(Events.ERROR, forwardMessage);
|
18531
|
-
var
|
18461
|
+
var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
|
18462
|
+
isTypeSupported: function isTypeSupported() {
|
18463
|
+
return false;
|
18464
|
+
}
|
18465
|
+
};
|
18466
|
+
var m2tsTypeSupported = {
|
18467
|
+
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
18468
|
+
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
18469
|
+
ac3: false
|
18470
|
+
};
|
18532
18471
|
|
18533
18472
|
// navigator.vendor is not always available in Web Worker
|
18534
18473
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -19106,32 +19045,13 @@
|
|
19106
19045
|
_this.altAudio = false;
|
19107
19046
|
_this.audioOnly = false;
|
19108
19047
|
_this.fragPlaying = null;
|
19048
|
+
_this.onvplaying = null;
|
19049
|
+
_this.onvseeked = null;
|
19109
19050
|
_this.fragLastKbps = 0;
|
19110
19051
|
_this.couldBacktrack = false;
|
19111
19052
|
_this.backtrackFragment = null;
|
19112
19053
|
_this.audioCodecSwitch = false;
|
19113
19054
|
_this.videoBuffer = null;
|
19114
|
-
_this.onMediaPlaying = function () {
|
19115
|
-
// tick to speed up FRAG_CHANGED triggering
|
19116
|
-
_this.tick();
|
19117
|
-
};
|
19118
|
-
_this.onMediaSeeked = function () {
|
19119
|
-
var media = _this.media;
|
19120
|
-
var currentTime = media ? media.currentTime : null;
|
19121
|
-
if (isFiniteNumber(currentTime)) {
|
19122
|
-
_this.log("Media seeked to " + currentTime.toFixed(3));
|
19123
|
-
}
|
19124
|
-
|
19125
|
-
// If seeked was issued before buffer was appended do not tick immediately
|
19126
|
-
var bufferInfo = _this.getMainFwdBufferInfo();
|
19127
|
-
if (bufferInfo === null || bufferInfo.len === 0) {
|
19128
|
-
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
19129
|
-
return;
|
19130
|
-
}
|
19131
|
-
|
19132
|
-
// tick to speed up FRAG_CHANGED triggering
|
19133
|
-
_this.tick();
|
19134
|
-
};
|
19135
19055
|
_this._registerListeners();
|
19136
19056
|
return _this;
|
19137
19057
|
}
|
@@ -19171,8 +19091,6 @@
|
|
19171
19091
|
};
|
19172
19092
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
19173
19093
|
this._unregisterListeners();
|
19174
|
-
// @ts-ignore
|
19175
|
-
this.onMediaPlaying = this.onMediaSeeked = null;
|
19176
19094
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
19177
19095
|
};
|
19178
19096
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -19487,15 +19405,18 @@
|
|
19487
19405
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
19488
19406
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
19489
19407
|
var media = data.media;
|
19490
|
-
|
19491
|
-
|
19408
|
+
this.onvplaying = this.onMediaPlaying.bind(this);
|
19409
|
+
this.onvseeked = this.onMediaSeeked.bind(this);
|
19410
|
+
media.addEventListener('playing', this.onvplaying);
|
19411
|
+
media.addEventListener('seeked', this.onvseeked);
|
19492
19412
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
19493
19413
|
};
|
19494
19414
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
19495
19415
|
var media = this.media;
|
19496
|
-
if (media) {
|
19497
|
-
media.removeEventListener('playing', this.
|
19498
|
-
media.removeEventListener('seeked', this.
|
19416
|
+
if (media && this.onvplaying && this.onvseeked) {
|
19417
|
+
media.removeEventListener('playing', this.onvplaying);
|
19418
|
+
media.removeEventListener('seeked', this.onvseeked);
|
19419
|
+
this.onvplaying = this.onvseeked = null;
|
19499
19420
|
this.videoBuffer = null;
|
19500
19421
|
}
|
19501
19422
|
this.fragPlaying = null;
|
@@ -19505,6 +19426,27 @@
|
|
19505
19426
|
}
|
19506
19427
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
19507
19428
|
};
|
19429
|
+
_proto.onMediaPlaying = function onMediaPlaying() {
|
19430
|
+
// tick to speed up FRAG_CHANGED triggering
|
19431
|
+
this.tick();
|
19432
|
+
};
|
19433
|
+
_proto.onMediaSeeked = function onMediaSeeked() {
|
19434
|
+
var media = this.media;
|
19435
|
+
var currentTime = media ? media.currentTime : null;
|
19436
|
+
if (isFiniteNumber(currentTime)) {
|
19437
|
+
this.log("Media seeked to " + currentTime.toFixed(3));
|
19438
|
+
}
|
19439
|
+
|
19440
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
19441
|
+
var bufferInfo = this.getMainFwdBufferInfo();
|
19442
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
19443
|
+
this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
19444
|
+
return;
|
19445
|
+
}
|
19446
|
+
|
19447
|
+
// tick to speed up FRAG_CHANGED triggering
|
19448
|
+
this.tick();
|
19449
|
+
};
|
19508
19450
|
_proto.onManifestLoading = function onManifestLoading() {
|
19509
19451
|
// reset buffer on manifest loading
|
19510
19452
|
this.log('Trigger BUFFER_RESET');
|
@@ -21078,7 +21020,7 @@
|
|
21078
21020
|
* Get the video-dev/hls.js package version.
|
21079
21021
|
*/
|
21080
21022
|
function get() {
|
21081
|
-
return "1.5.2
|
21023
|
+
return "1.5.2";
|
21082
21024
|
}
|
21083
21025
|
}, {
|
21084
21026
|
key: "Events",
|