hls.js 1.5.14-0.canary.10431 → 1.5.14-0.canary.10432
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.js +316 -232
- package/dist/hls.js.d.ts +4 -2
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +316 -235
- 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 +244 -168
- 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 +244 -165
- 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 +1 -1
- package/src/controller/base-stream-controller.ts +5 -4
- package/src/demux/audio/aacdemuxer.ts +3 -3
- package/src/demux/audio/ac3-demuxer.ts +1 -1
- package/src/demux/inject-worker.ts +38 -4
- package/src/demux/transmuxer-interface.ts +98 -67
- package/src/demux/transmuxer-worker.ts +110 -76
- package/src/demux/transmuxer.ts +29 -16
- package/src/demux/tsdemuxer.ts +47 -24
- package/src/hls.ts +2 -1
- package/src/remux/mp4-remuxer.ts +24 -23
- package/src/remux/passthrough-remuxer.ts +22 -7
- package/src/version.ts +1 -0
package/dist/hls.light.mjs
CHANGED
@@ -420,7 +420,7 @@ function enableLogs(debugConfig, context, id) {
|
|
420
420
|
// Some browsers don't allow to use bind on console object anyway
|
421
421
|
// fallback to default if needed
|
422
422
|
try {
|
423
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.14-0.canary.
|
423
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.14-0.canary.10432"}`);
|
424
424
|
} catch (e) {
|
425
425
|
/* log fn threw an exception. All logger methods are no-ops. */
|
426
426
|
return createLogger();
|
@@ -12684,6 +12684,10 @@ class BaseStreamController extends TaskLoop {
|
|
12684
12684
|
}
|
12685
12685
|
onHandlerDestroying() {
|
12686
12686
|
this.stopLoad();
|
12687
|
+
if (this.transmuxer) {
|
12688
|
+
this.transmuxer.destroy();
|
12689
|
+
this.transmuxer = null;
|
12690
|
+
}
|
12687
12691
|
super.onHandlerDestroying();
|
12688
12692
|
// @ts-ignore
|
12689
12693
|
this.hls = this.onMediaSeeking = this.onMediaEnded = null;
|
@@ -13807,10 +13811,8 @@ class BaseStreamController extends TaskLoop {
|
|
13807
13811
|
return `${this.playlistLabel()} ${frag.level} (frag:[${((_ref = pts ? frag.startPTS : frag.start) != null ? _ref : NaN).toFixed(3)}-${((_ref2 = pts ? frag.endPTS : frag.end) != null ? _ref2 : NaN).toFixed(3)}]`;
|
13808
13812
|
}
|
13809
13813
|
resetTransmuxer() {
|
13810
|
-
|
13811
|
-
|
13812
|
-
this.transmuxer = null;
|
13813
|
-
}
|
13814
|
+
var _this$transmuxer2;
|
13815
|
+
(_this$transmuxer2 = this.transmuxer) == null ? void 0 : _this$transmuxer2.reset();
|
13814
13816
|
}
|
13815
13817
|
recoverWorkerError(data) {
|
13816
13818
|
if (data.event === 'demuxerWorker') {
|
@@ -13859,29 +13861,66 @@ function changeTypeSupported() {
|
|
13859
13861
|
return typeof (sourceBuffer == null ? void 0 : (_sourceBuffer$prototy = sourceBuffer.prototype) == null ? void 0 : _sourceBuffer$prototy.changeType) === 'function';
|
13860
13862
|
}
|
13861
13863
|
|
13864
|
+
const version = "1.5.14-0.canary.10432";
|
13865
|
+
|
13862
13866
|
// ensure the worker ends up in the bundle
|
13863
13867
|
// If the worker should not be included this gets aliased to empty.js
|
13868
|
+
const workerStore = {};
|
13864
13869
|
function hasUMDWorker() {
|
13865
13870
|
return typeof __HLS_WORKER_BUNDLE__ === 'function';
|
13866
13871
|
}
|
13867
13872
|
function injectWorker() {
|
13873
|
+
const workerContext = workerStore[version];
|
13874
|
+
if (workerContext) {
|
13875
|
+
workerContext.clientCount++;
|
13876
|
+
return workerContext;
|
13877
|
+
}
|
13868
13878
|
const blob = new self.Blob([`var exports={};var module={exports:exports};function define(f){f()};define.amd=true;(${__HLS_WORKER_BUNDLE__.toString()})(true);`], {
|
13869
13879
|
type: 'text/javascript'
|
13870
13880
|
});
|
13871
13881
|
const objectURL = self.URL.createObjectURL(blob);
|
13872
13882
|
const worker = new self.Worker(objectURL);
|
13873
|
-
|
13883
|
+
const result = {
|
13874
13884
|
worker,
|
13875
|
-
objectURL
|
13885
|
+
objectURL,
|
13886
|
+
clientCount: 1
|
13876
13887
|
};
|
13888
|
+
workerStore[version] = result;
|
13889
|
+
return result;
|
13877
13890
|
}
|
13878
13891
|
function loadWorker(path) {
|
13892
|
+
const workerContext = workerStore[path];
|
13893
|
+
if (workerContext) {
|
13894
|
+
workerContext.clientCount++;
|
13895
|
+
return workerContext;
|
13896
|
+
}
|
13879
13897
|
const scriptURL = new self.URL(path, self.location.href).href;
|
13880
13898
|
const worker = new self.Worker(scriptURL);
|
13881
|
-
|
13899
|
+
const result = {
|
13882
13900
|
worker,
|
13883
|
-
scriptURL
|
13901
|
+
scriptURL,
|
13902
|
+
clientCount: 1
|
13884
13903
|
};
|
13904
|
+
workerStore[path] = result;
|
13905
|
+
return result;
|
13906
|
+
}
|
13907
|
+
function removeWorkerFromStore(path) {
|
13908
|
+
const workerContext = workerStore[path || version];
|
13909
|
+
if (workerContext) {
|
13910
|
+
const clientCount = workerContext.clientCount--;
|
13911
|
+
if (clientCount === 1) {
|
13912
|
+
const {
|
13913
|
+
worker,
|
13914
|
+
objectURL
|
13915
|
+
} = workerContext;
|
13916
|
+
delete workerStore[path || version];
|
13917
|
+
if (objectURL) {
|
13918
|
+
// revoke the Object URL that was used to create transmuxer worker, so as not to leak it
|
13919
|
+
self.URL.revokeObjectURL(objectURL);
|
13920
|
+
}
|
13921
|
+
worker.terminate();
|
13922
|
+
}
|
13923
|
+
}
|
13885
13924
|
}
|
13886
13925
|
|
13887
13926
|
function dummyTrack(type = '', inputTimeScale = 90000) {
|
@@ -14558,7 +14597,7 @@ class AACDemuxer extends BaseAudioDemuxer {
|
|
14558
14597
|
}
|
14559
14598
|
|
14560
14599
|
// Source for probe info - https://wiki.multimedia.cx/index.php?title=ADTS
|
14561
|
-
static probe(data) {
|
14600
|
+
static probe(data, logger) {
|
14562
14601
|
if (!data) {
|
14563
14602
|
return false;
|
14564
14603
|
}
|
@@ -15478,7 +15517,8 @@ class SampleAesDecrypter {
|
|
15478
15517
|
|
15479
15518
|
const PACKET_LENGTH = 188;
|
15480
15519
|
class TSDemuxer {
|
15481
|
-
constructor(observer, config, typeSupported) {
|
15520
|
+
constructor(observer, config, typeSupported, logger) {
|
15521
|
+
this.logger = void 0;
|
15482
15522
|
this.observer = void 0;
|
15483
15523
|
this.config = void 0;
|
15484
15524
|
this.typeSupported = void 0;
|
@@ -15498,9 +15538,10 @@ class TSDemuxer {
|
|
15498
15538
|
this.observer = observer;
|
15499
15539
|
this.config = config;
|
15500
15540
|
this.typeSupported = typeSupported;
|
15541
|
+
this.logger = logger;
|
15501
15542
|
this.videoParser = null;
|
15502
15543
|
}
|
15503
|
-
static probe(data) {
|
15544
|
+
static probe(data, logger) {
|
15504
15545
|
const syncOffset = TSDemuxer.syncOffset(data);
|
15505
15546
|
if (syncOffset > 0) {
|
15506
15547
|
logger.warn(`MPEG2-TS detected but first sync word found @ offset ${syncOffset}`);
|
@@ -15662,7 +15703,7 @@ class TSDemuxer {
|
|
15662
15703
|
switch (pid) {
|
15663
15704
|
case videoPid:
|
15664
15705
|
if (stt) {
|
15665
|
-
if (videoData && (pes = parsePES(videoData))) {
|
15706
|
+
if (videoData && (pes = parsePES(videoData, this.logger))) {
|
15666
15707
|
if (this.videoParser === null) {
|
15667
15708
|
switch (videoTrack.segmentCodec) {
|
15668
15709
|
case 'avc':
|
@@ -15686,7 +15727,7 @@ class TSDemuxer {
|
|
15686
15727
|
break;
|
15687
15728
|
case audioPid:
|
15688
15729
|
if (stt) {
|
15689
|
-
if (audioData && (pes = parsePES(audioData))) {
|
15730
|
+
if (audioData && (pes = parsePES(audioData, this.logger))) {
|
15690
15731
|
switch (audioTrack.segmentCodec) {
|
15691
15732
|
case 'aac':
|
15692
15733
|
this.parseAACPES(audioTrack, pes);
|
@@ -15708,7 +15749,7 @@ class TSDemuxer {
|
|
15708
15749
|
break;
|
15709
15750
|
case id3Pid:
|
15710
15751
|
if (stt) {
|
15711
|
-
if (id3Data && (pes = parsePES(id3Data))) {
|
15752
|
+
if (id3Data && (pes = parsePES(id3Data, this.logger))) {
|
15712
15753
|
this.parseID3PES(id3Track, pes);
|
15713
15754
|
}
|
15714
15755
|
id3Data = {
|
@@ -15726,14 +15767,14 @@ class TSDemuxer {
|
|
15726
15767
|
offset += data[offset] + 1;
|
15727
15768
|
}
|
15728
15769
|
pmtId = this._pmtId = parsePAT(data, offset);
|
15729
|
-
// logger.log('PMT PID:' + this._pmtId);
|
15770
|
+
// this.logger.log('PMT PID:' + this._pmtId);
|
15730
15771
|
break;
|
15731
15772
|
case pmtId:
|
15732
15773
|
{
|
15733
15774
|
if (stt) {
|
15734
15775
|
offset += data[offset] + 1;
|
15735
15776
|
}
|
15736
|
-
const parsedPIDs = parsePMT(data, offset, this.typeSupported, isSampleAes, this.observer);
|
15777
|
+
const parsedPIDs = parsePMT(data, offset, this.typeSupported, isSampleAes, this.observer, this.logger);
|
15737
15778
|
|
15738
15779
|
// only update track id if track PID found while parsing PMT
|
15739
15780
|
// this is to avoid resetting the PID to -1 in case
|
@@ -15756,7 +15797,7 @@ class TSDemuxer {
|
|
15756
15797
|
id3Track.pid = id3Pid;
|
15757
15798
|
}
|
15758
15799
|
if (unknownPID !== null && !pmtParsed) {
|
15759
|
-
logger.warn(`MPEG-TS PMT found at ${start} after unknown PID '${unknownPID}'. Backtracking to sync byte @${syncOffset} to parse all TS packets.`);
|
15800
|
+
this.logger.warn(`MPEG-TS PMT found at ${start} after unknown PID '${unknownPID}'. Backtracking to sync byte @${syncOffset} to parse all TS packets.`);
|
15760
15801
|
unknownPID = null;
|
15761
15802
|
// we set it to -188, the += 188 in the for loop will reset start to 0
|
15762
15803
|
start = syncOffset - 188;
|
@@ -15776,7 +15817,7 @@ class TSDemuxer {
|
|
15776
15817
|
}
|
15777
15818
|
}
|
15778
15819
|
if (tsPacketErrors > 0) {
|
15779
|
-
emitParsingError(this.observer, new Error(`Found ${tsPacketErrors} TS packet/s that do not start with 0x47`));
|
15820
|
+
emitParsingError(this.observer, new Error(`Found ${tsPacketErrors} TS packet/s that do not start with 0x47`), undefined, this.logger);
|
15780
15821
|
}
|
15781
15822
|
videoTrack.pesData = videoData;
|
15782
15823
|
audioTrack.pesData = audioData;
|
@@ -15826,7 +15867,7 @@ class TSDemuxer {
|
|
15826
15867
|
const id3Data = id3Track.pesData;
|
15827
15868
|
// try to parse last PES packets
|
15828
15869
|
let pes;
|
15829
|
-
if (videoData && (pes = parsePES(videoData))) {
|
15870
|
+
if (videoData && (pes = parsePES(videoData, this.logger))) {
|
15830
15871
|
if (this.videoParser === null) {
|
15831
15872
|
switch (videoTrack.segmentCodec) {
|
15832
15873
|
case 'avc':
|
@@ -15842,7 +15883,7 @@ class TSDemuxer {
|
|
15842
15883
|
// either avcData null or PES truncated, keep it for next frag parsing
|
15843
15884
|
videoTrack.pesData = videoData;
|
15844
15885
|
}
|
15845
|
-
if (audioData && (pes = parsePES(audioData))) {
|
15886
|
+
if (audioData && (pes = parsePES(audioData, this.logger))) {
|
15846
15887
|
switch (audioTrack.segmentCodec) {
|
15847
15888
|
case 'aac':
|
15848
15889
|
this.parseAACPES(audioTrack, pes);
|
@@ -15854,13 +15895,13 @@ class TSDemuxer {
|
|
15854
15895
|
audioTrack.pesData = null;
|
15855
15896
|
} else {
|
15856
15897
|
if (audioData != null && audioData.size) {
|
15857
|
-
logger.log('last AAC PES packet truncated,might overlap between fragments');
|
15898
|
+
this.logger.log('last AAC PES packet truncated,might overlap between fragments');
|
15858
15899
|
}
|
15859
15900
|
|
15860
15901
|
// either audioData null or PES truncated, keep it for next frag parsing
|
15861
15902
|
audioTrack.pesData = audioData;
|
15862
15903
|
}
|
15863
|
-
if (id3Data && (pes = parsePES(id3Data))) {
|
15904
|
+
if (id3Data && (pes = parsePES(id3Data, this.logger))) {
|
15864
15905
|
this.parseID3PES(id3Track, pes);
|
15865
15906
|
id3Track.pesData = null;
|
15866
15907
|
} else {
|
@@ -15934,7 +15975,7 @@ class TSDemuxer {
|
|
15934
15975
|
} else {
|
15935
15976
|
reason = 'No ADTS header found in AAC PES';
|
15936
15977
|
}
|
15937
|
-
emitParsingError(this.observer, new Error(reason), recoverable);
|
15978
|
+
emitParsingError(this.observer, new Error(reason), recoverable, this.logger);
|
15938
15979
|
if (!recoverable) {
|
15939
15980
|
return;
|
15940
15981
|
}
|
@@ -15949,7 +15990,7 @@ class TSDemuxer {
|
|
15949
15990
|
const frameDuration = getFrameDuration(track.samplerate);
|
15950
15991
|
pts = aacOverFlow.sample.pts + frameDuration;
|
15951
15992
|
} else {
|
15952
|
-
logger.warn('[tsdemuxer]: AAC PES unknown PTS');
|
15993
|
+
this.logger.warn('[tsdemuxer]: AAC PES unknown PTS');
|
15953
15994
|
return;
|
15954
15995
|
}
|
15955
15996
|
|
@@ -15979,7 +16020,7 @@ class TSDemuxer {
|
|
15979
16020
|
let offset = 0;
|
15980
16021
|
const pts = pes.pts;
|
15981
16022
|
if (pts === undefined) {
|
15982
|
-
logger.warn('[tsdemuxer]: MPEG PES unknown PTS');
|
16023
|
+
this.logger.warn('[tsdemuxer]: MPEG PES unknown PTS');
|
15983
16024
|
return;
|
15984
16025
|
}
|
15985
16026
|
while (offset < length) {
|
@@ -16002,7 +16043,7 @@ class TSDemuxer {
|
|
16002
16043
|
}
|
16003
16044
|
parseID3PES(id3Track, pes) {
|
16004
16045
|
if (pes.pts === undefined) {
|
16005
|
-
logger.warn('[tsdemuxer]: ID3 PES unknown PTS');
|
16046
|
+
this.logger.warn('[tsdemuxer]: ID3 PES unknown PTS');
|
16006
16047
|
return;
|
16007
16048
|
}
|
16008
16049
|
const id3Sample = _extends({}, pes, {
|
@@ -16020,7 +16061,7 @@ function parsePAT(data, offset) {
|
|
16020
16061
|
// skip the PSI header and parse the first PMT entry
|
16021
16062
|
return (data[offset + 10] & 0x1f) << 8 | data[offset + 11];
|
16022
16063
|
}
|
16023
|
-
function parsePMT(data, offset, typeSupported, isSampleAes, observer) {
|
16064
|
+
function parsePMT(data, offset, typeSupported, isSampleAes, observer, logger) {
|
16024
16065
|
const result = {
|
16025
16066
|
audioPid: -1,
|
16026
16067
|
videoPid: -1,
|
@@ -16042,7 +16083,7 @@ function parsePMT(data, offset, typeSupported, isSampleAes, observer) {
|
|
16042
16083
|
case 0xcf:
|
16043
16084
|
// SAMPLE-AES AAC
|
16044
16085
|
if (!isSampleAes) {
|
16045
|
-
logEncryptedSamplesFoundInUnencryptedStream('ADTS AAC');
|
16086
|
+
logEncryptedSamplesFoundInUnencryptedStream('ADTS AAC', this.logger);
|
16046
16087
|
break;
|
16047
16088
|
}
|
16048
16089
|
/* falls through */
|
@@ -16064,7 +16105,7 @@ function parsePMT(data, offset, typeSupported, isSampleAes, observer) {
|
|
16064
16105
|
case 0xdb:
|
16065
16106
|
// SAMPLE-AES AVC
|
16066
16107
|
if (!isSampleAes) {
|
16067
|
-
logEncryptedSamplesFoundInUnencryptedStream('H.264');
|
16108
|
+
logEncryptedSamplesFoundInUnencryptedStream('H.264', this.logger);
|
16068
16109
|
break;
|
16069
16110
|
}
|
16070
16111
|
/* falls through */
|
@@ -16092,7 +16133,7 @@ function parsePMT(data, offset, typeSupported, isSampleAes, observer) {
|
|
16092
16133
|
case 0xc1:
|
16093
16134
|
// SAMPLE-AES AC3
|
16094
16135
|
if (!isSampleAes) {
|
16095
|
-
logEncryptedSamplesFoundInUnencryptedStream('AC-3');
|
16136
|
+
logEncryptedSamplesFoundInUnencryptedStream('AC-3', this.logger);
|
16096
16137
|
break;
|
16097
16138
|
}
|
16098
16139
|
/* falls through */
|
@@ -16128,12 +16169,12 @@ function parsePMT(data, offset, typeSupported, isSampleAes, observer) {
|
|
16128
16169
|
case 0xc2: // SAMPLE-AES EC3
|
16129
16170
|
/* falls through */
|
16130
16171
|
case 0x87:
|
16131
|
-
emitParsingError(observer, new Error('Unsupported EC-3 in M2TS found'));
|
16172
|
+
emitParsingError(observer, new Error('Unsupported EC-3 in M2TS found'), undefined, this.logger);
|
16132
16173
|
return result;
|
16133
16174
|
case 0x24:
|
16134
16175
|
// ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
|
16135
16176
|
{
|
16136
|
-
emitParsingError(observer, new Error('Unsupported HEVC in M2TS found'));
|
16177
|
+
emitParsingError(observer, new Error('Unsupported HEVC in M2TS found'), undefined, this.logger);
|
16137
16178
|
return result;
|
16138
16179
|
}
|
16139
16180
|
}
|
@@ -16143,7 +16184,7 @@ function parsePMT(data, offset, typeSupported, isSampleAes, observer) {
|
|
16143
16184
|
}
|
16144
16185
|
return result;
|
16145
16186
|
}
|
16146
|
-
function emitParsingError(observer, error, levelRetry) {
|
16187
|
+
function emitParsingError(observer, error, levelRetry, logger) {
|
16147
16188
|
logger.warn(`parsing error: ${error.message}`);
|
16148
16189
|
observer.emit(Events.ERROR, Events.ERROR, {
|
16149
16190
|
type: ErrorTypes.MEDIA_ERROR,
|
@@ -16154,10 +16195,10 @@ function emitParsingError(observer, error, levelRetry) {
|
|
16154
16195
|
reason: error.message
|
16155
16196
|
});
|
16156
16197
|
}
|
16157
|
-
function logEncryptedSamplesFoundInUnencryptedStream(type) {
|
16198
|
+
function logEncryptedSamplesFoundInUnencryptedStream(type, logger) {
|
16158
16199
|
logger.log(`${type} with AES-128-CBC encryption found in unencrypted stream`);
|
16159
16200
|
}
|
16160
|
-
function parsePES(stream) {
|
16201
|
+
function parsePES(stream, logger) {
|
16161
16202
|
let i = 0;
|
16162
16203
|
let frag;
|
16163
16204
|
let pesLen;
|
@@ -17042,7 +17083,8 @@ const AC3_SAMPLES_PER_FRAME = 1536;
|
|
17042
17083
|
let chromeVersion = null;
|
17043
17084
|
let safariWebkitVersion = null;
|
17044
17085
|
class MP4Remuxer {
|
17045
|
-
constructor(observer, config, typeSupported,
|
17086
|
+
constructor(observer, config, typeSupported, logger) {
|
17087
|
+
this.logger = void 0;
|
17046
17088
|
this.observer = void 0;
|
17047
17089
|
this.config = void 0;
|
17048
17090
|
this.typeSupported = void 0;
|
@@ -17058,6 +17100,7 @@ class MP4Remuxer {
|
|
17058
17100
|
this.observer = observer;
|
17059
17101
|
this.config = config;
|
17060
17102
|
this.typeSupported = typeSupported;
|
17103
|
+
this.logger = logger;
|
17061
17104
|
this.ISGenerated = false;
|
17062
17105
|
if (chromeVersion === null) {
|
17063
17106
|
const userAgent = navigator.userAgent || '';
|
@@ -17074,16 +17117,16 @@ class MP4Remuxer {
|
|
17074
17117
|
this.config = this.videoTrackConfig = this._initPTS = this._initDTS = null;
|
17075
17118
|
}
|
17076
17119
|
resetTimeStamp(defaultTimeStamp) {
|
17077
|
-
logger.log('[mp4-remuxer]: initPTS & initDTS reset');
|
17120
|
+
this.logger.log('[mp4-remuxer]: initPTS & initDTS reset');
|
17078
17121
|
this._initPTS = this._initDTS = defaultTimeStamp;
|
17079
17122
|
}
|
17080
17123
|
resetNextTimestamp() {
|
17081
|
-
logger.log('[mp4-remuxer]: reset next timestamp');
|
17124
|
+
this.logger.log('[mp4-remuxer]: reset next timestamp');
|
17082
17125
|
this.isVideoContiguous = false;
|
17083
17126
|
this.isAudioContiguous = false;
|
17084
17127
|
}
|
17085
17128
|
resetInitSegment() {
|
17086
|
-
logger.log('[mp4-remuxer]: ISGenerated flag reset');
|
17129
|
+
this.logger.log('[mp4-remuxer]: ISGenerated flag reset');
|
17087
17130
|
this.ISGenerated = false;
|
17088
17131
|
this.videoTrackConfig = undefined;
|
17089
17132
|
}
|
@@ -17102,7 +17145,7 @@ class MP4Remuxer {
|
|
17102
17145
|
}
|
17103
17146
|
}, videoSamples[0].pts);
|
17104
17147
|
if (rolloverDetected) {
|
17105
|
-
logger.debug('PTS rollover detected');
|
17148
|
+
this.logger.debug('PTS rollover detected');
|
17106
17149
|
}
|
17107
17150
|
return startPTS;
|
17108
17151
|
}
|
@@ -17146,14 +17189,14 @@ class MP4Remuxer {
|
|
17146
17189
|
if (!isVideoContiguous && this.config.forceKeyFrameOnDiscontinuity) {
|
17147
17190
|
independent = true;
|
17148
17191
|
if (firstKeyFrameIndex > 0) {
|
17149
|
-
logger.warn(`[mp4-remuxer]: Dropped ${firstKeyFrameIndex} out of ${length} video samples due to a missing keyframe`);
|
17192
|
+
this.logger.warn(`[mp4-remuxer]: Dropped ${firstKeyFrameIndex} out of ${length} video samples due to a missing keyframe`);
|
17150
17193
|
const startPTS = this.getVideoStartPts(videoTrack.samples);
|
17151
17194
|
videoTrack.samples = videoTrack.samples.slice(firstKeyFrameIndex);
|
17152
17195
|
videoTrack.dropped += firstKeyFrameIndex;
|
17153
17196
|
videoTimeOffset += (videoTrack.samples[0].pts - startPTS) / videoTrack.inputTimeScale;
|
17154
17197
|
firstKeyFramePTS = videoTimeOffset;
|
17155
17198
|
} else if (firstKeyFrameIndex === -1) {
|
17156
|
-
logger.warn(`[mp4-remuxer]: No keyframe found out of ${length} video samples`);
|
17199
|
+
this.logger.warn(`[mp4-remuxer]: No keyframe found out of ${length} video samples`);
|
17157
17200
|
independent = false;
|
17158
17201
|
}
|
17159
17202
|
}
|
@@ -17175,7 +17218,7 @@ class MP4Remuxer {
|
|
17175
17218
|
if (enoughAudioSamples) {
|
17176
17219
|
// if initSegment was generated without audio samples, regenerate it again
|
17177
17220
|
if (!audioTrack.samplerate) {
|
17178
|
-
logger.warn('[mp4-remuxer]: regenerate InitSegment as audio detected');
|
17221
|
+
this.logger.warn('[mp4-remuxer]: regenerate InitSegment as audio detected');
|
17179
17222
|
initSegment = this.generateIS(audioTrack, videoTrack, timeOffset, accurateTimeOffset);
|
17180
17223
|
}
|
17181
17224
|
audio = this.remuxAudio(audioTrack, audioTimeOffset, this.isAudioContiguous, accurateTimeOffset, hasVideo || enoughVideoSamples || playlistType === PlaylistLevelType.AUDIO ? videoTimeOffset : undefined);
|
@@ -17183,7 +17226,7 @@ class MP4Remuxer {
|
|
17183
17226
|
const audioTrackLength = audio ? audio.endPTS - audio.startPTS : 0;
|
17184
17227
|
// if initSegment was generated without video samples, regenerate it again
|
17185
17228
|
if (!videoTrack.inputTimeScale) {
|
17186
|
-
logger.warn('[mp4-remuxer]: regenerate InitSegment as video detected');
|
17229
|
+
this.logger.warn('[mp4-remuxer]: regenerate InitSegment as video detected');
|
17187
17230
|
initSegment = this.generateIS(audioTrack, videoTrack, timeOffset, accurateTimeOffset);
|
17188
17231
|
}
|
17189
17232
|
video = this.remuxVideo(videoTrack, videoTimeOffset, isVideoContiguous, audioTrackLength);
|
@@ -17389,9 +17432,9 @@ class MP4Remuxer {
|
|
17389
17432
|
const foundOverlap = delta < -1;
|
17390
17433
|
if (foundHole || foundOverlap) {
|
17391
17434
|
if (foundHole) {
|
17392
|
-
logger.warn(`${(track.segmentCodec || '').toUpperCase()}: ${toMsFromMpegTsClock(delta, true)} ms (${delta}dts) hole between fragments detected at ${timeOffset.toFixed(3)}`);
|
17435
|
+
this.logger.warn(`${(track.segmentCodec || '').toUpperCase()}: ${toMsFromMpegTsClock(delta, true)} ms (${delta}dts) hole between fragments detected at ${timeOffset.toFixed(3)}`);
|
17393
17436
|
} else {
|
17394
|
-
logger.warn(`${(track.segmentCodec || '').toUpperCase()}: ${toMsFromMpegTsClock(-delta, true)} ms (${delta}dts) overlapping between fragments detected at ${timeOffset.toFixed(3)}`);
|
17437
|
+
this.logger.warn(`${(track.segmentCodec || '').toUpperCase()}: ${toMsFromMpegTsClock(-delta, true)} ms (${delta}dts) overlapping between fragments detected at ${timeOffset.toFixed(3)}`);
|
17395
17438
|
}
|
17396
17439
|
if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
|
17397
17440
|
firstDTS = nextAvcDts;
|
@@ -17420,7 +17463,7 @@ class MP4Remuxer {
|
|
17420
17463
|
}
|
17421
17464
|
}
|
17422
17465
|
}
|
17423
|
-
logger.log(`Video: Initial PTS/DTS adjusted: ${toMsFromMpegTsClock(firstPTS, true)}/${toMsFromMpegTsClock(firstDTS, true)}, delta: ${toMsFromMpegTsClock(delta, true)} ms`);
|
17466
|
+
this.logger.log(`Video: Initial PTS/DTS adjusted: ${toMsFromMpegTsClock(firstPTS, true)}/${toMsFromMpegTsClock(firstDTS, true)}, delta: ${toMsFromMpegTsClock(delta, true)} ms`);
|
17424
17467
|
}
|
17425
17468
|
}
|
17426
17469
|
}
|
@@ -17520,7 +17563,7 @@ class MP4Remuxer {
|
|
17520
17563
|
} else {
|
17521
17564
|
stretchedLastFrame = true;
|
17522
17565
|
}
|
17523
|
-
logger.log(`[mp4-remuxer]: It is approximately ${deltaToFrameEnd / 90} ms to the next segment; using duration ${mp4SampleDuration / 90} ms for the last video frame.`);
|
17566
|
+
this.logger.log(`[mp4-remuxer]: It is approximately ${deltaToFrameEnd / 90} ms to the next segment; using duration ${mp4SampleDuration / 90} ms for the last video frame.`);
|
17524
17567
|
} else {
|
17525
17568
|
mp4SampleDuration = lastFrameDuration;
|
17526
17569
|
}
|
@@ -17548,7 +17591,7 @@ class MP4Remuxer {
|
|
17548
17591
|
// Fix for "CNN special report, with CC" in test-streams (Safari browser only)
|
17549
17592
|
// Ignore DTS when frame durations are irregular. Safari MSE does not handle this leading to gaps.
|
17550
17593
|
if (maxPtsDelta - minPtsDelta < maxDtsDelta - minDtsDelta && averageSampleDuration / maxDtsDelta < 0.025 && outputSamples[0].cts === 0) {
|
17551
|
-
logger.warn('Found irregular gaps in sample duration. Using PTS instead of DTS to determine MP4 sample duration.');
|
17594
|
+
this.logger.warn('Found irregular gaps in sample duration. Using PTS instead of DTS to determine MP4 sample duration.');
|
17552
17595
|
let dts = firstDTS;
|
17553
17596
|
for (let i = 0, len = outputSamples.length; i < len; i++) {
|
17554
17597
|
const nextDts = dts + outputSamples[i].duration;
|
@@ -17673,7 +17716,7 @@ class MP4Remuxer {
|
|
17673
17716
|
// When remuxing with video, if we're overlapping by more than a duration, drop this sample to stay in sync
|
17674
17717
|
if (delta <= -maxAudioFramesDrift * inputSampleDuration && alignedWithVideo) {
|
17675
17718
|
if (i === 0) {
|
17676
|
-
logger.warn(`Audio frame @ ${(pts / inputTimeScale).toFixed(3)}s overlaps nextAudioPts by ${Math.round(1000 * delta / inputTimeScale)} ms.`);
|
17719
|
+
this.logger.warn(`Audio frame @ ${(pts / inputTimeScale).toFixed(3)}s overlaps nextAudioPts by ${Math.round(1000 * delta / inputTimeScale)} ms.`);
|
17677
17720
|
this.nextAudioPts = nextAudioPts = nextPts = pts;
|
17678
17721
|
}
|
17679
17722
|
} // eslint-disable-line brace-style
|
@@ -17695,12 +17738,12 @@ class MP4Remuxer {
|
|
17695
17738
|
if (i === 0) {
|
17696
17739
|
this.nextAudioPts = nextAudioPts = nextPts;
|
17697
17740
|
}
|
17698
|
-
logger.warn(`[mp4-remuxer]: Injecting ${missing} audio frame @ ${(nextPts / inputTimeScale).toFixed(3)}s due to ${Math.round(1000 * delta / inputTimeScale)} ms gap.`);
|
17741
|
+
this.logger.warn(`[mp4-remuxer]: Injecting ${missing} audio frame @ ${(nextPts / inputTimeScale).toFixed(3)}s due to ${Math.round(1000 * delta / inputTimeScale)} ms gap.`);
|
17699
17742
|
for (let j = 0; j < missing; j++) {
|
17700
17743
|
const newStamp = Math.max(nextPts, 0);
|
17701
17744
|
let fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
|
17702
17745
|
if (!fillFrame) {
|
17703
|
-
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
17746
|
+
this.logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
17704
17747
|
fillFrame = sample.unit.subarray();
|
17705
17748
|
}
|
17706
17749
|
inputSamples.splice(i, 0, {
|
@@ -17899,7 +17942,8 @@ class Mp4Sample {
|
|
17899
17942
|
}
|
17900
17943
|
|
17901
17944
|
class PassThroughRemuxer {
|
17902
|
-
constructor() {
|
17945
|
+
constructor(observer, config, typeSupported, logger) {
|
17946
|
+
this.logger = void 0;
|
17903
17947
|
this.emitInitSegment = false;
|
17904
17948
|
this.audioCodec = void 0;
|
17905
17949
|
this.videoCodec = void 0;
|
@@ -17907,6 +17951,7 @@ class PassThroughRemuxer {
|
|
17907
17951
|
this.initPTS = null;
|
17908
17952
|
this.initTracks = void 0;
|
17909
17953
|
this.lastEndTime = null;
|
17954
|
+
this.logger = logger;
|
17910
17955
|
}
|
17911
17956
|
destroy() {}
|
17912
17957
|
resetTimeStamp(defaultInitPTS) {
|
@@ -17964,7 +18009,7 @@ class PassThroughRemuxer {
|
|
17964
18009
|
id: 'main'
|
17965
18010
|
};
|
17966
18011
|
} else {
|
17967
|
-
logger.warn('[passthrough-remuxer.ts]: initSegment does not contain moov or trak boxes.');
|
18012
|
+
this.logger.warn('[passthrough-remuxer.ts]: initSegment does not contain moov or trak boxes.');
|
17968
18013
|
}
|
17969
18014
|
this.initTracks = tracks;
|
17970
18015
|
}
|
@@ -18006,7 +18051,7 @@ class PassThroughRemuxer {
|
|
18006
18051
|
}
|
18007
18052
|
if (!((_initData2 = initData) != null && _initData2.length)) {
|
18008
18053
|
// We can't remux if the initSegment could not be generated
|
18009
|
-
logger.warn('[passthrough-remuxer.ts]: Failed to generate initSegment.');
|
18054
|
+
this.logger.warn('[passthrough-remuxer.ts]: Failed to generate initSegment.');
|
18010
18055
|
return result;
|
18011
18056
|
}
|
18012
18057
|
if (this.emitInitSegment) {
|
@@ -18019,7 +18064,7 @@ class PassThroughRemuxer {
|
|
18019
18064
|
if (isInvalidInitPts(initPTS, decodeTime, timeOffset, duration) || initSegment.timescale !== initPTS.timescale && accurateTimeOffset) {
|
18020
18065
|
initSegment.initPTS = decodeTime - timeOffset;
|
18021
18066
|
if (initPTS && initPTS.timescale === 1) {
|
18022
|
-
logger.warn(`Adjusting initPTS @${timeOffset} from ${initPTS.baseTime / initPTS.timescale} to ${initSegment.initPTS}`);
|
18067
|
+
this.logger.warn(`Adjusting initPTS @${timeOffset} from ${initPTS.baseTime / initPTS.timescale} to ${initSegment.initPTS}`);
|
18023
18068
|
}
|
18024
18069
|
this.initPTS = initPTS = {
|
18025
18070
|
baseTime: initSegment.initPTS,
|
@@ -18032,7 +18077,7 @@ class PassThroughRemuxer {
|
|
18032
18077
|
if (duration > 0) {
|
18033
18078
|
this.lastEndTime = endTime;
|
18034
18079
|
} else {
|
18035
|
-
logger.warn('Duration parsed from mp4 should be greater than zero');
|
18080
|
+
this.logger.warn('Duration parsed from mp4 should be greater than zero');
|
18036
18081
|
this.resetNextTimestamp();
|
18037
18082
|
}
|
18038
18083
|
const hasAudio = !!initData.audio;
|
@@ -18090,12 +18135,12 @@ function getParsedTrackCodec(track, type) {
|
|
18090
18135
|
return getCodecCompatibleName(parsedCodec, preferManagedMediaSource);
|
18091
18136
|
}
|
18092
18137
|
const result = 'mp4a.40.5';
|
18093
|
-
logger.info(`Parsed audio codec "${parsedCodec}" or audio object type not handled. Using "${result}"`);
|
18138
|
+
this.logger.info(`Parsed audio codec "${parsedCodec}" or audio object type not handled. Using "${result}"`);
|
18094
18139
|
return result;
|
18095
18140
|
}
|
18096
18141
|
// Provide defaults based on codec type
|
18097
18142
|
// This allows for some playback of some fmp4 playlists without CODECS defined in manifest
|
18098
|
-
logger.warn(`Unhandled video codec "${parsedCodec}"`);
|
18143
|
+
this.logger.warn(`Unhandled video codec "${parsedCodec}"`);
|
18099
18144
|
if (parsedCodec === 'hvc1' || parsedCodec === 'hev1') {
|
18100
18145
|
return 'hvc1.1.6.L120.90';
|
18101
18146
|
}
|
@@ -18105,16 +18150,12 @@ function getParsedTrackCodec(track, type) {
|
|
18105
18150
|
return 'avc1.42e01e';
|
18106
18151
|
}
|
18107
18152
|
|
18108
|
-
/** returns `undefined` is `self` is missing, e.g. in node */
|
18109
|
-
const optionalSelf = typeof self !== 'undefined' ? self : undefined;
|
18110
|
-
|
18111
18153
|
let now;
|
18112
18154
|
// performance.now() not available on WebWorker, at least on Safari Desktop
|
18113
18155
|
try {
|
18114
18156
|
now = self.performance.now.bind(self.performance);
|
18115
18157
|
} catch (err) {
|
18116
|
-
|
18117
|
-
now = optionalSelf == null ? void 0 : optionalSelf.Date.now;
|
18158
|
+
now = Date.now;
|
18118
18159
|
}
|
18119
18160
|
const muxConfig = [{
|
18120
18161
|
demux: MP4Demuxer,
|
@@ -18130,8 +18171,9 @@ const muxConfig = [{
|
|
18130
18171
|
remux: MP4Remuxer
|
18131
18172
|
}];
|
18132
18173
|
class Transmuxer {
|
18133
|
-
constructor(observer, typeSupported, config, vendor, id) {
|
18134
|
-
this.
|
18174
|
+
constructor(observer, typeSupported, config, vendor, id, logger) {
|
18175
|
+
this.asyncResult = false;
|
18176
|
+
this.logger = void 0;
|
18135
18177
|
this.observer = void 0;
|
18136
18178
|
this.typeSupported = void 0;
|
18137
18179
|
this.config = void 0;
|
@@ -18149,6 +18191,7 @@ class Transmuxer {
|
|
18149
18191
|
this.config = config;
|
18150
18192
|
this.vendor = vendor;
|
18151
18193
|
this.id = id;
|
18194
|
+
this.logger = logger;
|
18152
18195
|
}
|
18153
18196
|
configure(transmuxConfig) {
|
18154
18197
|
this.transmuxConfig = transmuxConfig;
|
@@ -18203,6 +18246,7 @@ class Transmuxer {
|
|
18203
18246
|
}
|
18204
18247
|
uintData = new Uint8Array(decryptedData);
|
18205
18248
|
} else {
|
18249
|
+
this.asyncResult = true;
|
18206
18250
|
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(decryptedData => {
|
18207
18251
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
18208
18252
|
// the decrypted data has been transmuxed
|
@@ -18217,7 +18261,7 @@ class Transmuxer {
|
|
18217
18261
|
if (resetMuxers) {
|
18218
18262
|
const error = this.configureTransmuxer(uintData);
|
18219
18263
|
if (error) {
|
18220
|
-
logger.warn(`[transmuxer] ${error.message}`);
|
18264
|
+
this.logger.warn(`[transmuxer] ${error.message}`);
|
18221
18265
|
this.observer.emit(Events.ERROR, Events.ERROR, {
|
18222
18266
|
type: ErrorTypes.MEDIA_ERROR,
|
18223
18267
|
details: ErrorDetails.FRAG_PARSING_ERROR,
|
@@ -18239,6 +18283,7 @@ class Transmuxer {
|
|
18239
18283
|
this.resetContiguity();
|
18240
18284
|
}
|
18241
18285
|
const result = this.transmux(uintData, keyData, timeOffset, accurateTimeOffset, chunkMeta);
|
18286
|
+
this.asyncResult = isPromise(result);
|
18242
18287
|
const currentState = this.currentTransmuxState;
|
18243
18288
|
currentState.contiguous = true;
|
18244
18289
|
currentState.discontinuity = false;
|
@@ -18257,6 +18302,7 @@ class Transmuxer {
|
|
18257
18302
|
decryptionPromise
|
18258
18303
|
} = this;
|
18259
18304
|
if (decryptionPromise) {
|
18305
|
+
this.asyncResult = true;
|
18260
18306
|
// Upon resolution, the decryption promise calls push() and returns its TransmuxerResult up the stack. Therefore
|
18261
18307
|
// only flushing is required for async decryption
|
18262
18308
|
return decryptionPromise.then(() => {
|
@@ -18284,10 +18330,15 @@ class Transmuxer {
|
|
18284
18330
|
if (!demuxer || !remuxer) {
|
18285
18331
|
// If probing failed, then Hls.js has been given content its not able to handle
|
18286
18332
|
stats.executeEnd = now();
|
18287
|
-
|
18333
|
+
const emptyResults = [emptyResult(chunkMeta)];
|
18334
|
+
if (this.asyncResult) {
|
18335
|
+
return Promise.resolve(emptyResults);
|
18336
|
+
}
|
18337
|
+
return emptyResults;
|
18288
18338
|
}
|
18289
18339
|
const demuxResultOrPromise = demuxer.flush(timeOffset);
|
18290
18340
|
if (isPromise(demuxResultOrPromise)) {
|
18341
|
+
this.asyncResult = true;
|
18291
18342
|
// Decrypt final SAMPLE-AES samples
|
18292
18343
|
return demuxResultOrPromise.then(demuxResult => {
|
18293
18344
|
this.flushRemux(transmuxResults, demuxResult, chunkMeta);
|
@@ -18295,6 +18346,9 @@ class Transmuxer {
|
|
18295
18346
|
});
|
18296
18347
|
}
|
18297
18348
|
this.flushRemux(transmuxResults, demuxResultOrPromise, chunkMeta);
|
18349
|
+
if (this.asyncResult) {
|
18350
|
+
return Promise.resolve(transmuxResults);
|
18351
|
+
}
|
18298
18352
|
return transmuxResults;
|
18299
18353
|
}
|
18300
18354
|
flushRemux(transmuxResults, demuxResult, chunkMeta) {
|
@@ -18308,7 +18362,7 @@ class Transmuxer {
|
|
18308
18362
|
accurateTimeOffset,
|
18309
18363
|
timeOffset
|
18310
18364
|
} = this.currentTransmuxState;
|
18311
|
-
logger.log(`[transmuxer.ts]: Flushed
|
18365
|
+
this.logger.log(`[transmuxer.ts]: Flushed ${this.id} sn: ${chunkMeta.sn}${chunkMeta.part > -1 ? ' p: ' + chunkMeta.part : ''} of ${this.id === PlaylistLevelType.MAIN ? 'level' : 'track'} ${chunkMeta.level}`);
|
18312
18366
|
const remuxResult = this.remuxer.remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, accurateTimeOffset, true, this.id);
|
18313
18367
|
transmuxResults.push({
|
18314
18368
|
remuxResult,
|
@@ -18401,7 +18455,7 @@ class Transmuxer {
|
|
18401
18455
|
let mux;
|
18402
18456
|
for (let i = 0, len = muxConfig.length; i < len; i++) {
|
18403
18457
|
var _muxConfig$i$demux;
|
18404
|
-
if ((_muxConfig$i$demux = muxConfig[i].demux) != null && _muxConfig$i$demux.probe(data)) {
|
18458
|
+
if ((_muxConfig$i$demux = muxConfig[i].demux) != null && _muxConfig$i$demux.probe(data, this.logger)) {
|
18405
18459
|
mux = muxConfig[i];
|
18406
18460
|
break;
|
18407
18461
|
}
|
@@ -18415,10 +18469,10 @@ class Transmuxer {
|
|
18415
18469
|
const Remuxer = mux.remux;
|
18416
18470
|
const Demuxer = mux.demux;
|
18417
18471
|
if (!remuxer || !(remuxer instanceof Remuxer)) {
|
18418
|
-
this.remuxer = new Remuxer(observer, config, typeSupported,
|
18472
|
+
this.remuxer = new Remuxer(observer, config, typeSupported, this.logger);
|
18419
18473
|
}
|
18420
18474
|
if (!demuxer || !(demuxer instanceof Demuxer)) {
|
18421
|
-
this.demuxer = new Demuxer(observer, config, typeSupported);
|
18475
|
+
this.demuxer = new Demuxer(observer, config, typeSupported, this.logger);
|
18422
18476
|
this.probe = Demuxer.probe;
|
18423
18477
|
}
|
18424
18478
|
}
|
@@ -18823,31 +18877,96 @@ var eventemitter3 = {exports: {}};
|
|
18823
18877
|
var eventemitter3Exports = eventemitter3.exports;
|
18824
18878
|
var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
|
18825
18879
|
|
18880
|
+
let transmuxerInstanceCount = 0;
|
18826
18881
|
class TransmuxerInterface {
|
18827
|
-
constructor(
|
18882
|
+
constructor(_hls, id, onTransmuxComplete, onFlush) {
|
18828
18883
|
this.error = null;
|
18829
18884
|
this.hls = void 0;
|
18830
18885
|
this.id = void 0;
|
18886
|
+
this.instanceNo = transmuxerInstanceCount++;
|
18831
18887
|
this.observer = void 0;
|
18832
18888
|
this.frag = null;
|
18833
18889
|
this.part = null;
|
18834
18890
|
this.useWorker = void 0;
|
18835
18891
|
this.workerContext = null;
|
18836
|
-
this.onwmsg = void 0;
|
18837
18892
|
this.transmuxer = null;
|
18838
18893
|
this.onTransmuxComplete = void 0;
|
18839
18894
|
this.onFlush = void 0;
|
18840
|
-
|
18841
|
-
|
18895
|
+
this.onWorkerMessage = event => {
|
18896
|
+
const data = event.data;
|
18897
|
+
const hls = this.hls;
|
18898
|
+
if (!hls || !(data != null && data.event) || data.instanceNo !== this.instanceNo) {
|
18899
|
+
return;
|
18900
|
+
}
|
18901
|
+
switch (data.event) {
|
18902
|
+
case 'init':
|
18903
|
+
{
|
18904
|
+
var _this$workerContext;
|
18905
|
+
const objectURL = (_this$workerContext = this.workerContext) == null ? void 0 : _this$workerContext.objectURL;
|
18906
|
+
if (objectURL) {
|
18907
|
+
// revoke the Object URL that was used to create transmuxer worker, so as not to leak it
|
18908
|
+
self.URL.revokeObjectURL(objectURL);
|
18909
|
+
}
|
18910
|
+
break;
|
18911
|
+
}
|
18912
|
+
case 'transmuxComplete':
|
18913
|
+
{
|
18914
|
+
this.handleTransmuxComplete(data.data);
|
18915
|
+
break;
|
18916
|
+
}
|
18917
|
+
case 'flush':
|
18918
|
+
{
|
18919
|
+
this.onFlush(data.data);
|
18920
|
+
break;
|
18921
|
+
}
|
18922
|
+
|
18923
|
+
// pass logs from the worker thread to the main logger
|
18924
|
+
case 'workerLog':
|
18925
|
+
{
|
18926
|
+
if (hls.logger[data.data.logType]) {
|
18927
|
+
hls.logger[data.data.logType](data.data.message);
|
18928
|
+
}
|
18929
|
+
break;
|
18930
|
+
}
|
18931
|
+
default:
|
18932
|
+
{
|
18933
|
+
data.data = data.data || {};
|
18934
|
+
data.data.frag = this.frag;
|
18935
|
+
data.data.part = this.part;
|
18936
|
+
data.data.id = this.id;
|
18937
|
+
hls.trigger(data.event, data.data);
|
18938
|
+
break;
|
18939
|
+
}
|
18940
|
+
}
|
18941
|
+
};
|
18942
|
+
this.onWorkerError = event => {
|
18943
|
+
if (!this.hls) {
|
18944
|
+
return;
|
18945
|
+
}
|
18946
|
+
const error = new Error(`${event.message} (${event.filename}:${event.lineno})`);
|
18947
|
+
this.hls.config.enableWorker = false;
|
18948
|
+
this.hls.logger.warn(`Error in "${this.id}" Web Worker, fallback to inline`);
|
18949
|
+
this.hls.trigger(Events.ERROR, {
|
18950
|
+
type: ErrorTypes.OTHER_ERROR,
|
18951
|
+
details: ErrorDetails.INTERNAL_EXCEPTION,
|
18952
|
+
fatal: false,
|
18953
|
+
event: 'demuxerWorker',
|
18954
|
+
error
|
18955
|
+
});
|
18956
|
+
};
|
18957
|
+
const config = _hls.config;
|
18958
|
+
this.hls = _hls;
|
18842
18959
|
this.id = id;
|
18843
18960
|
this.useWorker = !!config.enableWorker;
|
18844
18961
|
this.onTransmuxComplete = onTransmuxComplete;
|
18845
18962
|
this.onFlush = onFlush;
|
18846
18963
|
const forwardMessage = (ev, data) => {
|
18847
18964
|
data = data || {};
|
18848
|
-
data.frag = this.frag;
|
18849
|
-
data.id = this.id;
|
18965
|
+
data.frag = this.frag || undefined;
|
18850
18966
|
if (ev === Events.ERROR) {
|
18967
|
+
data = data;
|
18968
|
+
data.parent = this.id;
|
18969
|
+
data.part = this.part;
|
18851
18970
|
this.error = data.error;
|
18852
18971
|
}
|
18853
18972
|
this.hls.trigger(ev, data);
|
@@ -18859,6 +18978,7 @@ class TransmuxerInterface {
|
|
18859
18978
|
this.observer.on(Events.ERROR, forwardMessage);
|
18860
18979
|
const m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
|
18861
18980
|
if (this.useWorker && typeof Worker !== 'undefined') {
|
18981
|
+
const logger = this.hls.logger;
|
18862
18982
|
const canCreateWorker = config.workerPath || hasUMDWorker();
|
18863
18983
|
if (canCreateWorker) {
|
18864
18984
|
try {
|
@@ -18869,61 +18989,63 @@ class TransmuxerInterface {
|
|
18869
18989
|
logger.log(`injecting Web Worker for "${id}"`);
|
18870
18990
|
this.workerContext = injectWorker();
|
18871
18991
|
}
|
18872
|
-
this.onwmsg = event => this.onWorkerMessage(event);
|
18873
18992
|
const {
|
18874
18993
|
worker
|
18875
18994
|
} = this.workerContext;
|
18876
|
-
worker.addEventListener('message', this.
|
18877
|
-
worker.
|
18878
|
-
const error = new Error(`${event.message} (${event.filename}:${event.lineno})`);
|
18879
|
-
config.enableWorker = false;
|
18880
|
-
logger.warn(`Error in "${id}" Web Worker, fallback to inline`);
|
18881
|
-
this.hls.trigger(Events.ERROR, {
|
18882
|
-
type: ErrorTypes.OTHER_ERROR,
|
18883
|
-
details: ErrorDetails.INTERNAL_EXCEPTION,
|
18884
|
-
fatal: false,
|
18885
|
-
event: 'demuxerWorker',
|
18886
|
-
error
|
18887
|
-
});
|
18888
|
-
};
|
18995
|
+
worker.addEventListener('message', this.onWorkerMessage);
|
18996
|
+
worker.addEventListener('error', this.onWorkerError);
|
18889
18997
|
worker.postMessage({
|
18998
|
+
instanceNo: this.instanceNo,
|
18890
18999
|
cmd: 'init',
|
18891
19000
|
typeSupported: m2tsTypeSupported,
|
18892
|
-
|
18893
|
-
id: id,
|
19001
|
+
id,
|
18894
19002
|
config: JSON.stringify(config)
|
18895
19003
|
});
|
18896
19004
|
} catch (err) {
|
18897
19005
|
logger.warn(`Error setting up "${id}" Web Worker, fallback to inline`, err);
|
18898
|
-
this.
|
19006
|
+
this.terminateWorker();
|
18899
19007
|
this.error = null;
|
18900
|
-
this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, '', id);
|
19008
|
+
this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, '', id, _hls.logger);
|
18901
19009
|
}
|
18902
19010
|
return;
|
18903
19011
|
}
|
18904
19012
|
}
|
18905
|
-
this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, '', id);
|
19013
|
+
this.transmuxer = new Transmuxer(this.observer, m2tsTypeSupported, config, '', id, _hls.logger);
|
18906
19014
|
}
|
18907
|
-
|
19015
|
+
reset() {
|
19016
|
+
this.frag = null;
|
19017
|
+
this.part = null;
|
19018
|
+
if (this.workerContext) {
|
19019
|
+
const instanceNo = this.instanceNo;
|
19020
|
+
this.instanceNo = transmuxerInstanceCount++;
|
19021
|
+
const config = this.hls.config;
|
19022
|
+
const m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
|
19023
|
+
this.workerContext.worker.postMessage({
|
19024
|
+
instanceNo: this.instanceNo,
|
19025
|
+
cmd: 'reset',
|
19026
|
+
resetNo: instanceNo,
|
19027
|
+
typeSupported: m2tsTypeSupported,
|
19028
|
+
id: this.id,
|
19029
|
+
config: JSON.stringify(config)
|
19030
|
+
});
|
19031
|
+
}
|
19032
|
+
}
|
19033
|
+
terminateWorker() {
|
18908
19034
|
if (this.workerContext) {
|
18909
19035
|
const {
|
18910
|
-
worker
|
18911
|
-
objectURL
|
19036
|
+
worker
|
18912
19037
|
} = this.workerContext;
|
18913
|
-
if (objectURL) {
|
18914
|
-
// revoke the Object URL that was used to create transmuxer worker, so as not to leak it
|
18915
|
-
self.URL.revokeObjectURL(objectURL);
|
18916
|
-
}
|
18917
|
-
worker.removeEventListener('message', this.onwmsg);
|
18918
|
-
worker.onerror = null;
|
18919
|
-
worker.terminate();
|
18920
19038
|
this.workerContext = null;
|
19039
|
+
worker.removeEventListener('message', this.onWorkerMessage);
|
19040
|
+
worker.removeEventListener('error', this.onWorkerError);
|
19041
|
+
removeWorkerFromStore(this.hls.config.workerPath);
|
18921
19042
|
}
|
18922
19043
|
}
|
18923
19044
|
destroy() {
|
18924
19045
|
if (this.workerContext) {
|
18925
|
-
this.
|
18926
|
-
|
19046
|
+
this.terminateWorker();
|
19047
|
+
// @ts-ignore
|
19048
|
+
this.onWorkerMessage = this.onWorkerError = null;
|
18927
19049
|
} else {
|
18928
19050
|
const transmuxer = this.transmuxer;
|
18929
19051
|
if (transmuxer) {
|
@@ -18936,6 +19058,7 @@ class TransmuxerInterface {
|
|
18936
19058
|
observer.removeAllListeners();
|
18937
19059
|
}
|
18938
19060
|
this.frag = null;
|
19061
|
+
this.part = null;
|
18939
19062
|
// @ts-ignore
|
18940
19063
|
this.observer = null;
|
18941
19064
|
// @ts-ignore
|
@@ -18945,6 +19068,7 @@ class TransmuxerInterface {
|
|
18945
19068
|
var _frag$initSegment, _lastFrag$initSegment;
|
18946
19069
|
chunkMeta.transmuxing.start = self.performance.now();
|
18947
19070
|
const {
|
19071
|
+
instanceNo,
|
18948
19072
|
transmuxer
|
18949
19073
|
} = this;
|
18950
19074
|
const timeOffset = part ? part.start : frag.start;
|
@@ -18967,7 +19091,7 @@ class TransmuxerInterface {
|
|
18967
19091
|
const initSegmentChange = !(lastFrag && ((_frag$initSegment = frag.initSegment) == null ? void 0 : _frag$initSegment.url) === ((_lastFrag$initSegment = lastFrag.initSegment) == null ? void 0 : _lastFrag$initSegment.url));
|
18968
19092
|
const state = new TransmuxState(discontinuity, contiguous, accurateTimeOffset, trackSwitch, timeOffset, initSegmentChange);
|
18969
19093
|
if (!contiguous || discontinuity || initSegmentChange) {
|
18970
|
-
logger.log(`[transmuxer-interface, ${frag.type}]: Starting new transmux session for sn: ${chunkMeta.sn} p: ${chunkMeta.part} level: ${chunkMeta.level} id: ${chunkMeta.id}
|
19094
|
+
this.hls.logger.log(`[transmuxer-interface, ${frag.type}]: Starting new transmux session for sn: ${chunkMeta.sn} p: ${chunkMeta.part} level: ${chunkMeta.level} id: ${chunkMeta.id}
|
18971
19095
|
discontinuity: ${discontinuity}
|
18972
19096
|
trackSwitch: ${trackSwitch}
|
18973
19097
|
contiguous: ${contiguous}
|
@@ -18984,6 +19108,7 @@ class TransmuxerInterface {
|
|
18984
19108
|
if (this.workerContext) {
|
18985
19109
|
// post fragment payload as transferable objects for ArrayBuffer (no copy)
|
18986
19110
|
this.workerContext.worker.postMessage({
|
19111
|
+
instanceNo,
|
18987
19112
|
cmd: 'demux',
|
18988
19113
|
data,
|
18989
19114
|
decryptdata,
|
@@ -18993,14 +19118,12 @@ class TransmuxerInterface {
|
|
18993
19118
|
} else if (transmuxer) {
|
18994
19119
|
const transmuxResult = transmuxer.push(data, decryptdata, chunkMeta, state);
|
18995
19120
|
if (isPromise(transmuxResult)) {
|
18996
|
-
transmuxer.async = true;
|
18997
19121
|
transmuxResult.then(data => {
|
18998
19122
|
this.handleTransmuxComplete(data);
|
18999
19123
|
}).catch(error => {
|
19000
19124
|
this.transmuxerError(error, chunkMeta, 'transmuxer-interface push error');
|
19001
19125
|
});
|
19002
19126
|
} else {
|
19003
|
-
transmuxer.async = false;
|
19004
19127
|
this.handleTransmuxComplete(transmuxResult);
|
19005
19128
|
}
|
19006
19129
|
}
|
@@ -19008,20 +19131,18 @@ class TransmuxerInterface {
|
|
19008
19131
|
flush(chunkMeta) {
|
19009
19132
|
chunkMeta.transmuxing.start = self.performance.now();
|
19010
19133
|
const {
|
19134
|
+
instanceNo,
|
19011
19135
|
transmuxer
|
19012
19136
|
} = this;
|
19013
19137
|
if (this.workerContext) {
|
19014
19138
|
this.workerContext.worker.postMessage({
|
19139
|
+
instanceNo,
|
19015
19140
|
cmd: 'flush',
|
19016
19141
|
chunkMeta
|
19017
19142
|
});
|
19018
19143
|
} else if (transmuxer) {
|
19019
|
-
|
19020
|
-
|
19021
|
-
if (asyncFlush || transmuxer.async) {
|
19022
|
-
if (!isPromise(transmuxResult)) {
|
19023
|
-
transmuxResult = Promise.resolve(transmuxResult);
|
19024
|
-
}
|
19144
|
+
const transmuxResult = transmuxer.flush(chunkMeta);
|
19145
|
+
if (isPromise(transmuxResult)) {
|
19025
19146
|
transmuxResult.then(data => {
|
19026
19147
|
this.handleFlushResult(data, chunkMeta);
|
19027
19148
|
}).catch(error => {
|
@@ -19042,6 +19163,7 @@ class TransmuxerInterface {
|
|
19042
19163
|
details: ErrorDetails.FRAG_PARSING_ERROR,
|
19043
19164
|
chunkMeta,
|
19044
19165
|
frag: this.frag || undefined,
|
19166
|
+
part: this.part || undefined,
|
19045
19167
|
fatal: false,
|
19046
19168
|
error,
|
19047
19169
|
err: error,
|
@@ -19054,60 +19176,14 @@ class TransmuxerInterface {
|
|
19054
19176
|
});
|
19055
19177
|
this.onFlush(chunkMeta);
|
19056
19178
|
}
|
19057
|
-
onWorkerMessage(event) {
|
19058
|
-
const data = event.data;
|
19059
|
-
if (!(data != null && data.event)) {
|
19060
|
-
logger.warn(`worker message received with no ${data ? 'event name' : 'data'}`);
|
19061
|
-
return;
|
19062
|
-
}
|
19063
|
-
const hls = this.hls;
|
19064
|
-
if (!this.hls) {
|
19065
|
-
return;
|
19066
|
-
}
|
19067
|
-
switch (data.event) {
|
19068
|
-
case 'init':
|
19069
|
-
{
|
19070
|
-
var _this$workerContext;
|
19071
|
-
const objectURL = (_this$workerContext = this.workerContext) == null ? void 0 : _this$workerContext.objectURL;
|
19072
|
-
if (objectURL) {
|
19073
|
-
// revoke the Object URL that was used to create transmuxer worker, so as not to leak it
|
19074
|
-
self.URL.revokeObjectURL(objectURL);
|
19075
|
-
}
|
19076
|
-
break;
|
19077
|
-
}
|
19078
|
-
case 'transmuxComplete':
|
19079
|
-
{
|
19080
|
-
this.handleTransmuxComplete(data.data);
|
19081
|
-
break;
|
19082
|
-
}
|
19083
|
-
case 'flush':
|
19084
|
-
{
|
19085
|
-
this.onFlush(data.data);
|
19086
|
-
break;
|
19087
|
-
}
|
19088
|
-
|
19089
|
-
// pass logs from the worker thread to the main logger
|
19090
|
-
case 'workerLog':
|
19091
|
-
if (logger[data.data.logType]) {
|
19092
|
-
logger[data.data.logType](data.data.message);
|
19093
|
-
}
|
19094
|
-
break;
|
19095
|
-
default:
|
19096
|
-
{
|
19097
|
-
data.data = data.data || {};
|
19098
|
-
data.data.frag = this.frag;
|
19099
|
-
data.data.id = this.id;
|
19100
|
-
hls.trigger(data.event, data.data);
|
19101
|
-
break;
|
19102
|
-
}
|
19103
|
-
}
|
19104
|
-
}
|
19105
19179
|
configureTransmuxer(config) {
|
19106
19180
|
const {
|
19181
|
+
instanceNo,
|
19107
19182
|
transmuxer
|
19108
19183
|
} = this;
|
19109
19184
|
if (this.workerContext) {
|
19110
19185
|
this.workerContext.worker.postMessage({
|
19186
|
+
instanceNo,
|
19111
19187
|
cmd: 'configure',
|
19112
19188
|
config
|
19113
19189
|
});
|
@@ -20636,7 +20712,7 @@ class Hls {
|
|
20636
20712
|
* Get the video-dev/hls.js package version.
|
20637
20713
|
*/
|
20638
20714
|
static get version() {
|
20639
|
-
return
|
20715
|
+
return version;
|
20640
20716
|
}
|
20641
20717
|
|
20642
20718
|
/**
|