hls.js 1.5.7-0.canary.10015 → 1.5.7-0.canary.10016
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 +276 -161
- package/dist/hls.js.d.ts +13 -6
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +259 -128
- 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 +200 -71
- 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 +217 -104
- 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/abr-controller.ts +3 -0
- package/src/controller/audio-stream-controller.ts +26 -38
- package/src/controller/base-stream-controller.ts +5 -2
- package/src/controller/buffer-controller.ts +192 -56
- package/src/controller/buffer-operation-queue.ts +16 -19
- package/src/controller/fragment-tracker.ts +15 -11
- package/src/controller/stream-controller.ts +9 -0
- package/src/controller/subtitle-stream-controller.ts +1 -15
- package/src/hls.ts +7 -3
- package/src/utils/codecs.ts +1 -1
package/dist/hls.light.js
CHANGED
@@ -613,7 +613,7 @@
|
|
613
613
|
// Some browsers don't allow to use bind on console object anyway
|
614
614
|
// fallback to default if needed
|
615
615
|
try {
|
616
|
-
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.7-0.canary.
|
616
|
+
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.7-0.canary.10016");
|
617
617
|
} catch (e) {
|
618
618
|
/* log fn threw an exception. All logger methods are no-ops. */
|
619
619
|
return createLogger();
|
@@ -6813,6 +6813,9 @@
|
|
6813
6813
|
var fragCurrent = this.fragCurrent,
|
6814
6814
|
partCurrent = this.partCurrent,
|
6815
6815
|
hls = this.hls;
|
6816
|
+
if (hls.levels.length <= 1) {
|
6817
|
+
return hls.loadLevel;
|
6818
|
+
}
|
6816
6819
|
var maxAutoLevel = hls.maxAutoLevel,
|
6817
6820
|
config = hls.config,
|
6818
6821
|
minAutoLevel = hls.minAutoLevel;
|
@@ -7230,24 +7233,23 @@
|
|
7230
7233
|
this.executeNext(type);
|
7231
7234
|
}
|
7232
7235
|
};
|
7233
|
-
_proto.insertAbort = function insertAbort(operation, type) {
|
7234
|
-
var queue = this.queues[type];
|
7235
|
-
queue.unshift(operation);
|
7236
|
-
this.executeNext(type);
|
7237
|
-
};
|
7238
7236
|
_proto.appendBlocker = function appendBlocker(type) {
|
7239
|
-
var
|
7240
|
-
|
7241
|
-
|
7237
|
+
var _this = this;
|
7238
|
+
return new Promise(function (resolve) {
|
7239
|
+
var operation = {
|
7240
|
+
execute: resolve,
|
7241
|
+
onStart: function onStart() {},
|
7242
|
+
onComplete: function onComplete() {},
|
7243
|
+
onError: function onError() {}
|
7244
|
+
};
|
7245
|
+
_this.append(operation, type);
|
7242
7246
|
});
|
7243
|
-
|
7244
|
-
|
7245
|
-
|
7246
|
-
|
7247
|
-
|
7248
|
-
}
|
7249
|
-
this.append(operation, type);
|
7250
|
-
return promise;
|
7247
|
+
};
|
7248
|
+
_proto.unblockAudio = function unblockAudio(op) {
|
7249
|
+
var queue = this.queues.audio;
|
7250
|
+
if (queue[0] === op) {
|
7251
|
+
this.shiftAndExecuteNext('audio');
|
7252
|
+
}
|
7251
7253
|
};
|
7252
7254
|
_proto.executeNext = function executeNext(type) {
|
7253
7255
|
var queue = this.queues[type];
|
@@ -7282,7 +7284,7 @@
|
|
7282
7284
|
var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
|
7283
7285
|
var BufferController = /*#__PURE__*/function (_Logger) {
|
7284
7286
|
_inheritsLoose(BufferController, _Logger);
|
7285
|
-
function BufferController(hls) {
|
7287
|
+
function BufferController(hls, fragmentTracker) {
|
7286
7288
|
var _this;
|
7287
7289
|
_this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
|
7288
7290
|
// The level details used to determine duration, target-duration and live
|
@@ -7294,6 +7296,7 @@
|
|
7294
7296
|
// References to event listeners for each SourceBuffer, so that they can be referenced for event removal
|
7295
7297
|
_this.listeners = void 0;
|
7296
7298
|
_this.hls = void 0;
|
7299
|
+
_this.fragmentTracker = void 0;
|
7297
7300
|
// The number of BUFFER_CODEC events received before any sourceBuffers are created
|
7298
7301
|
_this.bufferCodecEventsExpected = 0;
|
7299
7302
|
// The total number of BUFFER_CODEC events received
|
@@ -7304,6 +7307,10 @@
|
|
7304
7307
|
_this.mediaSource = null;
|
7305
7308
|
// Last MP3 audio chunk appended
|
7306
7309
|
_this.lastMpegAudioChunk = null;
|
7310
|
+
// Audio fragment blocked from appending until corresponding video appends or context changes
|
7311
|
+
_this.blockedAudioAppend = null;
|
7312
|
+
// Keep track of video append position for unblocking audio
|
7313
|
+
_this.lastVideoAppendEnd = 0;
|
7307
7314
|
_this.appendSource = void 0;
|
7308
7315
|
// counters
|
7309
7316
|
_this.appendErrors = {
|
@@ -7334,7 +7341,10 @@
|
|
7334
7341
|
_this.log('Media source opened');
|
7335
7342
|
if (media) {
|
7336
7343
|
media.removeEventListener('emptied', _this._onMediaEmptied);
|
7337
|
-
_this.
|
7344
|
+
var durationAndRange = _this.getDurationAndRange();
|
7345
|
+
if (durationAndRange) {
|
7346
|
+
_this.updateMediaSource(durationAndRange);
|
7347
|
+
}
|
7338
7348
|
_this.hls.trigger(Events.MEDIA_ATTACHED, {
|
7339
7349
|
media: media,
|
7340
7350
|
mediaSource: mediaSource
|
@@ -7361,6 +7371,7 @@
|
|
7361
7371
|
}
|
7362
7372
|
};
|
7363
7373
|
_this.hls = hls;
|
7374
|
+
_this.fragmentTracker = fragmentTracker;
|
7364
7375
|
_this.appendSource = hls.config.preferManagedMediaSource;
|
7365
7376
|
_this._initSourceBuffer();
|
7366
7377
|
_this.registerListeners();
|
@@ -7375,7 +7386,7 @@
|
|
7375
7386
|
this.details = null;
|
7376
7387
|
this.lastMpegAudioChunk = null;
|
7377
7388
|
// @ts-ignore
|
7378
|
-
this.hls = null;
|
7389
|
+
this.hls = this.fragmentTracker = null;
|
7379
7390
|
// @ts-ignore
|
7380
7391
|
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
7381
7392
|
// @ts-ignore
|
@@ -7427,6 +7438,8 @@
|
|
7427
7438
|
audiovideo: 0
|
7428
7439
|
};
|
7429
7440
|
this.lastMpegAudioChunk = null;
|
7441
|
+
this.blockedAudioAppend = null;
|
7442
|
+
this.lastVideoAppendEnd = 0;
|
7430
7443
|
};
|
7431
7444
|
_proto.onManifestLoading = function onManifestLoading() {
|
7432
7445
|
this.bufferCodecEventsExpected = this._bufferCodecEventsTotal = 0;
|
@@ -7564,9 +7577,10 @@
|
|
7564
7577
|
var trackNames = Object.keys(data);
|
7565
7578
|
trackNames.forEach(function (trackName) {
|
7566
7579
|
if (sourceBufferCount) {
|
7580
|
+
var _track$buffer;
|
7567
7581
|
// check if SourceBuffer codec needs to change
|
7568
7582
|
var track = _this3.tracks[trackName];
|
7569
|
-
if (track && typeof track.buffer.changeType === 'function') {
|
7583
|
+
if (track && typeof ((_track$buffer = track.buffer) == null ? void 0 : _track$buffer.changeType) === 'function') {
|
7570
7584
|
var _trackCodec;
|
7571
7585
|
var _data$trackName = data[trackName],
|
7572
7586
|
id = _data$trackName.id,
|
@@ -7634,17 +7648,52 @@
|
|
7634
7648
|
};
|
7635
7649
|
operationQueue.append(operation, type, !!this.pendingTracks[type]);
|
7636
7650
|
};
|
7651
|
+
_proto.blockAudio = function blockAudio(partOrFrag) {
|
7652
|
+
var _this$fragmentTracker,
|
7653
|
+
_this5 = this;
|
7654
|
+
var pStart = partOrFrag.start;
|
7655
|
+
var pTime = pStart + partOrFrag.duration * 0.05;
|
7656
|
+
var atGap = ((_this$fragmentTracker = this.fragmentTracker.getAppendedFrag(pStart, PlaylistLevelType.MAIN)) == null ? void 0 : _this$fragmentTracker.gap) === true;
|
7657
|
+
if (atGap) {
|
7658
|
+
return;
|
7659
|
+
}
|
7660
|
+
var op = {
|
7661
|
+
execute: function execute() {
|
7662
|
+
var _this5$fragmentTracke;
|
7663
|
+
if (_this5.lastVideoAppendEnd > pTime || _this5.sourceBuffer.video && BufferHelper.isBuffered(_this5.sourceBuffer.video, pTime) || ((_this5$fragmentTracke = _this5.fragmentTracker.getAppendedFrag(pTime, PlaylistLevelType.MAIN)) == null ? void 0 : _this5$fragmentTracke.gap) === true) {
|
7664
|
+
_this5.blockedAudioAppend = null;
|
7665
|
+
_this5.operationQueue.shiftAndExecuteNext('audio');
|
7666
|
+
}
|
7667
|
+
},
|
7668
|
+
onStart: function onStart() {},
|
7669
|
+
onComplete: function onComplete() {},
|
7670
|
+
onError: function onError() {}
|
7671
|
+
};
|
7672
|
+
this.blockedAudioAppend = {
|
7673
|
+
op: op,
|
7674
|
+
frag: partOrFrag
|
7675
|
+
};
|
7676
|
+
this.operationQueue.append(op, 'audio', true);
|
7677
|
+
};
|
7678
|
+
_proto.unblockAudio = function unblockAudio() {
|
7679
|
+
var blockedAudioAppend = this.blockedAudioAppend;
|
7680
|
+
if (blockedAudioAppend) {
|
7681
|
+
this.blockedAudioAppend = null;
|
7682
|
+
this.operationQueue.unblockAudio(blockedAudioAppend.op);
|
7683
|
+
}
|
7684
|
+
};
|
7637
7685
|
_proto.onBufferAppending = function onBufferAppending(event, eventData) {
|
7638
|
-
var
|
7639
|
-
var
|
7640
|
-
operationQueue = this.operationQueue,
|
7686
|
+
var _this6 = this;
|
7687
|
+
var operationQueue = this.operationQueue,
|
7641
7688
|
tracks = this.tracks;
|
7642
7689
|
var data = eventData.data,
|
7643
7690
|
type = eventData.type,
|
7691
|
+
parent = eventData.parent,
|
7644
7692
|
frag = eventData.frag,
|
7645
7693
|
part = eventData.part,
|
7646
7694
|
chunkMeta = eventData.chunkMeta;
|
7647
7695
|
var chunkStats = chunkMeta.buffering[type];
|
7696
|
+
var sn = frag.sn;
|
7648
7697
|
var bufferAppendingStart = self.performance.now();
|
7649
7698
|
chunkStats.start = bufferAppendingStart;
|
7650
7699
|
var fragBuffering = frag.stats.buffering;
|
@@ -7667,21 +7716,50 @@
|
|
7667
7716
|
checkTimestampOffset = !this.lastMpegAudioChunk || chunkMeta.id === 1 || this.lastMpegAudioChunk.sn !== chunkMeta.sn;
|
7668
7717
|
this.lastMpegAudioChunk = chunkMeta;
|
7669
7718
|
}
|
7670
|
-
|
7719
|
+
|
7720
|
+
// Block audio append until overlapping video append
|
7721
|
+
var videoSb = this.sourceBuffer.video;
|
7722
|
+
if (videoSb && sn !== 'initSegment') {
|
7723
|
+
var partOrFrag = part || frag;
|
7724
|
+
var blockedAudioAppend = this.blockedAudioAppend;
|
7725
|
+
if (type === 'audio' && parent !== 'main' && !this.blockedAudioAppend) {
|
7726
|
+
var pStart = partOrFrag.start;
|
7727
|
+
var pTime = pStart + partOrFrag.duration * 0.05;
|
7728
|
+
var vbuffered = videoSb.buffered;
|
7729
|
+
var vappending = this.operationQueue.current('video');
|
7730
|
+
if (!vbuffered.length && !vappending) {
|
7731
|
+
// wait for video before appending audio
|
7732
|
+
this.blockAudio(partOrFrag);
|
7733
|
+
} else if (!vappending && !BufferHelper.isBuffered(videoSb, pTime) && this.lastVideoAppendEnd < pTime) {
|
7734
|
+
// audio is ahead of video
|
7735
|
+
this.blockAudio(partOrFrag);
|
7736
|
+
}
|
7737
|
+
} else if (type === 'video') {
|
7738
|
+
var videoAppendEnd = partOrFrag.end;
|
7739
|
+
if (blockedAudioAppend) {
|
7740
|
+
var audioStart = blockedAudioAppend.frag.start;
|
7741
|
+
if (videoAppendEnd > audioStart || videoAppendEnd < this.lastVideoAppendEnd || BufferHelper.isBuffered(videoSb, audioStart)) {
|
7742
|
+
this.unblockAudio();
|
7743
|
+
}
|
7744
|
+
}
|
7745
|
+
this.lastVideoAppendEnd = videoAppendEnd;
|
7746
|
+
}
|
7747
|
+
}
|
7748
|
+
var fragStart = (part || frag).start;
|
7671
7749
|
var operation = {
|
7672
7750
|
execute: function execute() {
|
7673
7751
|
chunkStats.executeStart = self.performance.now();
|
7674
7752
|
if (checkTimestampOffset) {
|
7675
|
-
var sb =
|
7753
|
+
var sb = _this6.sourceBuffer[type];
|
7676
7754
|
if (sb) {
|
7677
7755
|
var delta = fragStart - sb.timestampOffset;
|
7678
7756
|
if (Math.abs(delta) >= 0.1) {
|
7679
|
-
|
7757
|
+
_this6.log("Updating audio SourceBuffer timestampOffset to " + fragStart + " (delta: " + delta + ") sn: " + sn + ")");
|
7680
7758
|
sb.timestampOffset = fragStart;
|
7681
7759
|
}
|
7682
7760
|
}
|
7683
7761
|
}
|
7684
|
-
|
7762
|
+
_this6.appendExecutor(data, type);
|
7685
7763
|
},
|
7686
7764
|
onStart: function onStart() {
|
7687
7765
|
// logger.debug(`[buffer-controller]: ${type} SourceBuffer updatestart`);
|
@@ -7696,19 +7774,19 @@
|
|
7696
7774
|
if (partBuffering && partBuffering.first === 0) {
|
7697
7775
|
partBuffering.first = end;
|
7698
7776
|
}
|
7699
|
-
var sourceBuffer =
|
7777
|
+
var sourceBuffer = _this6.sourceBuffer;
|
7700
7778
|
var timeRanges = {};
|
7701
7779
|
for (var _type in sourceBuffer) {
|
7702
7780
|
timeRanges[_type] = BufferHelper.getBuffered(sourceBuffer[_type]);
|
7703
7781
|
}
|
7704
|
-
|
7782
|
+
_this6.appendErrors[type] = 0;
|
7705
7783
|
if (type === 'audio' || type === 'video') {
|
7706
|
-
|
7784
|
+
_this6.appendErrors.audiovideo = 0;
|
7707
7785
|
} else {
|
7708
|
-
|
7709
|
-
|
7786
|
+
_this6.appendErrors.audio = 0;
|
7787
|
+
_this6.appendErrors.video = 0;
|
7710
7788
|
}
|
7711
|
-
|
7789
|
+
_this6.hls.trigger(Events.BUFFER_APPENDED, {
|
7712
7790
|
type: type,
|
7713
7791
|
frag: frag,
|
7714
7792
|
part: part,
|
@@ -7736,51 +7814,57 @@
|
|
7736
7814
|
// let's stop appending any segments, and report BUFFER_FULL_ERROR error
|
7737
7815
|
event.details = ErrorDetails.BUFFER_FULL_ERROR;
|
7738
7816
|
} else {
|
7739
|
-
var appendErrorCount = ++
|
7817
|
+
var appendErrorCount = ++_this6.appendErrors[type];
|
7740
7818
|
event.details = ErrorDetails.BUFFER_APPEND_ERROR;
|
7741
7819
|
/* with UHD content, we could get loop of quota exceeded error until
|
7742
7820
|
browser is able to evict some data from sourcebuffer. Retrying can help recover.
|
7743
7821
|
*/
|
7744
|
-
|
7745
|
-
if (appendErrorCount >= hls.config.appendErrorMaxRetry) {
|
7822
|
+
_this6.warn("Failed " + appendErrorCount + "/" + _this6.hls.config.appendErrorMaxRetry + " times to append segment in \"" + type + "\" sourceBuffer");
|
7823
|
+
if (appendErrorCount >= _this6.hls.config.appendErrorMaxRetry) {
|
7746
7824
|
event.fatal = true;
|
7747
7825
|
}
|
7748
7826
|
}
|
7749
|
-
hls.trigger(Events.ERROR, event);
|
7827
|
+
_this6.hls.trigger(Events.ERROR, event);
|
7750
7828
|
}
|
7751
7829
|
};
|
7752
7830
|
operationQueue.append(operation, type, !!this.pendingTracks[type]);
|
7753
7831
|
};
|
7832
|
+
_proto.getFlushOp = function getFlushOp(type, start, end) {
|
7833
|
+
var _this7 = this;
|
7834
|
+
return {
|
7835
|
+
execute: function execute() {
|
7836
|
+
_this7.removeExecutor(type, start, end);
|
7837
|
+
},
|
7838
|
+
onStart: function onStart() {
|
7839
|
+
// logger.debug(`[buffer-controller]: Started flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`);
|
7840
|
+
},
|
7841
|
+
onComplete: function onComplete() {
|
7842
|
+
// logger.debug(`[buffer-controller]: Finished flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`);
|
7843
|
+
_this7.hls.trigger(Events.BUFFER_FLUSHED, {
|
7844
|
+
type: type
|
7845
|
+
});
|
7846
|
+
},
|
7847
|
+
onError: function onError(error) {
|
7848
|
+
_this7.warn("Failed to remove from " + type + " SourceBuffer", error);
|
7849
|
+
}
|
7850
|
+
};
|
7851
|
+
};
|
7754
7852
|
_proto.onBufferFlushing = function onBufferFlushing(event, data) {
|
7755
|
-
var
|
7853
|
+
var _this8 = this;
|
7756
7854
|
var operationQueue = this.operationQueue;
|
7757
|
-
var
|
7758
|
-
|
7759
|
-
|
7760
|
-
|
7761
|
-
|
7762
|
-
},
|
7763
|
-
onComplete: function onComplete() {
|
7764
|
-
// logger.debug(`[buffer-controller]: Finished flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`);
|
7765
|
-
_this6.hls.trigger(Events.BUFFER_FLUSHED, {
|
7766
|
-
type: type
|
7767
|
-
});
|
7768
|
-
},
|
7769
|
-
onError: function onError(error) {
|
7770
|
-
_this6.warn("Failed to remove from " + type + " SourceBuffer", error);
|
7771
|
-
}
|
7772
|
-
};
|
7773
|
-
};
|
7774
|
-
if (data.type) {
|
7775
|
-
operationQueue.append(flushOperation(data.type), data.type);
|
7855
|
+
var type = data.type,
|
7856
|
+
startOffset = data.startOffset,
|
7857
|
+
endOffset = data.endOffset;
|
7858
|
+
if (type) {
|
7859
|
+
operationQueue.append(this.getFlushOp(type, startOffset, endOffset), type);
|
7776
7860
|
} else {
|
7777
|
-
this.getSourceBufferTypes().forEach(function (
|
7778
|
-
operationQueue.append(
|
7861
|
+
this.getSourceBufferTypes().forEach(function (sbType) {
|
7862
|
+
operationQueue.append(_this8.getFlushOp(sbType, startOffset, endOffset), sbType);
|
7779
7863
|
});
|
7780
7864
|
}
|
7781
7865
|
};
|
7782
7866
|
_proto.onFragParsed = function onFragParsed(event, data) {
|
7783
|
-
var
|
7867
|
+
var _this9 = this;
|
7784
7868
|
var frag = data.frag,
|
7785
7869
|
part = data.part;
|
7786
7870
|
var buffersAppendedTo = [];
|
@@ -7802,7 +7886,7 @@
|
|
7802
7886
|
part.stats.buffering.end = now;
|
7803
7887
|
}
|
7804
7888
|
var stats = part ? part.stats : frag.stats;
|
7805
|
-
|
7889
|
+
_this9.hls.trigger(Events.FRAG_BUFFERED, {
|
7806
7890
|
frag: frag,
|
7807
7891
|
part: part,
|
7808
7892
|
stats: stats,
|
@@ -7822,14 +7906,17 @@
|
|
7822
7906
|
// an undefined data.type will mark all buffers as EOS.
|
7823
7907
|
;
|
7824
7908
|
_proto.onBufferEos = function onBufferEos(event, data) {
|
7825
|
-
var
|
7909
|
+
var _this10 = this;
|
7910
|
+
if (data.type === 'video') {
|
7911
|
+
this.unblockAudio();
|
7912
|
+
}
|
7826
7913
|
var ended = this.getSourceBufferTypes().reduce(function (acc, type) {
|
7827
|
-
var sb =
|
7914
|
+
var sb = _this10.sourceBuffer[type];
|
7828
7915
|
if (sb && (!data.type || data.type === type)) {
|
7829
7916
|
sb.ending = true;
|
7830
7917
|
if (!sb.ended) {
|
7831
7918
|
sb.ended = true;
|
7832
|
-
|
7919
|
+
_this10.log(type + " sourceBuffer now EOS");
|
7833
7920
|
}
|
7834
7921
|
}
|
7835
7922
|
return acc && !!(!sb || sb.ended);
|
@@ -7837,35 +7924,42 @@
|
|
7837
7924
|
if (ended) {
|
7838
7925
|
this.log("Queueing mediaSource.endOfStream()");
|
7839
7926
|
this.blockBuffers(function () {
|
7840
|
-
|
7841
|
-
var sb =
|
7927
|
+
_this10.getSourceBufferTypes().forEach(function (type) {
|
7928
|
+
var sb = _this10.sourceBuffer[type];
|
7842
7929
|
if (sb) {
|
7843
7930
|
sb.ending = false;
|
7844
7931
|
}
|
7845
7932
|
});
|
7846
|
-
var mediaSource =
|
7933
|
+
var mediaSource = _this10.mediaSource;
|
7847
7934
|
if (!mediaSource || mediaSource.readyState !== 'open') {
|
7848
7935
|
if (mediaSource) {
|
7849
|
-
|
7936
|
+
_this10.log("Could not call mediaSource.endOfStream(). mediaSource.readyState: " + mediaSource.readyState);
|
7850
7937
|
}
|
7851
7938
|
return;
|
7852
7939
|
}
|
7853
|
-
|
7940
|
+
_this10.log("Calling mediaSource.endOfStream()");
|
7854
7941
|
// Allow this to throw and be caught by the enqueueing function
|
7855
7942
|
mediaSource.endOfStream();
|
7856
7943
|
});
|
7857
7944
|
}
|
7858
7945
|
};
|
7859
7946
|
_proto.onLevelUpdated = function onLevelUpdated(event, _ref) {
|
7947
|
+
var _this11 = this;
|
7860
7948
|
var details = _ref.details;
|
7861
7949
|
if (!details.fragments.length) {
|
7862
7950
|
return;
|
7863
7951
|
}
|
7864
7952
|
this.details = details;
|
7953
|
+
var durationAndRange = this.getDurationAndRange();
|
7954
|
+
if (!durationAndRange) {
|
7955
|
+
return;
|
7956
|
+
}
|
7865
7957
|
if (this.getSourceBufferTypes().length) {
|
7866
|
-
this.blockBuffers(
|
7958
|
+
this.blockBuffers(function () {
|
7959
|
+
return _this11.updateMediaSource(durationAndRange);
|
7960
|
+
});
|
7867
7961
|
} else {
|
7868
|
-
this.
|
7962
|
+
this.updateMediaSource(durationAndRange);
|
7869
7963
|
}
|
7870
7964
|
};
|
7871
7965
|
_proto.trimBuffers = function trimBuffers() {
|
@@ -7898,7 +7992,7 @@
|
|
7898
7992
|
}
|
7899
7993
|
};
|
7900
7994
|
_proto.flushBackBuffer = function flushBackBuffer(currentTime, targetDuration, targetBackBufferPosition) {
|
7901
|
-
var
|
7995
|
+
var _this12 = this;
|
7902
7996
|
var details = this.details,
|
7903
7997
|
sourceBuffer = this.sourceBuffer;
|
7904
7998
|
var sourceBufferTypes = this.getSourceBufferTypes();
|
@@ -7908,20 +8002,20 @@
|
|
7908
8002
|
var buffered = BufferHelper.getBuffered(sb);
|
7909
8003
|
// when target buffer start exceeds actual buffer start
|
7910
8004
|
if (buffered.length > 0 && targetBackBufferPosition > buffered.start(0)) {
|
7911
|
-
|
8005
|
+
_this12.hls.trigger(Events.BACK_BUFFER_REACHED, {
|
7912
8006
|
bufferEnd: targetBackBufferPosition
|
7913
8007
|
});
|
7914
8008
|
|
7915
8009
|
// Support for deprecated event:
|
7916
8010
|
if (details != null && details.live) {
|
7917
|
-
|
8011
|
+
_this12.hls.trigger(Events.LIVE_BACK_BUFFER_REACHED, {
|
7918
8012
|
bufferEnd: targetBackBufferPosition
|
7919
8013
|
});
|
7920
8014
|
} else if (sb.ended && buffered.end(buffered.length - 1) - currentTime < targetDuration * 2) {
|
7921
|
-
|
8015
|
+
_this12.log("Cannot flush " + type + " back buffer while SourceBuffer is in ended state");
|
7922
8016
|
return;
|
7923
8017
|
}
|
7924
|
-
|
8018
|
+
_this12.hls.trigger(Events.BUFFER_FLUSHING, {
|
7925
8019
|
startOffset: 0,
|
7926
8020
|
endOffset: targetBackBufferPosition,
|
7927
8021
|
type: type
|
@@ -7931,7 +8025,7 @@
|
|
7931
8025
|
});
|
7932
8026
|
};
|
7933
8027
|
_proto.flushFrontBuffer = function flushFrontBuffer(currentTime, targetDuration, targetFrontBufferPosition) {
|
7934
|
-
var
|
8028
|
+
var _this13 = this;
|
7935
8029
|
var sourceBuffer = this.sourceBuffer;
|
7936
8030
|
var sourceBufferTypes = this.getSourceBufferTypes();
|
7937
8031
|
sourceBufferTypes.forEach(function (type) {
|
@@ -7949,10 +8043,10 @@
|
|
7949
8043
|
if (targetFrontBufferPosition > bufferStart || currentTime >= bufferStart && currentTime <= bufferEnd) {
|
7950
8044
|
return;
|
7951
8045
|
} else if (sb.ended && currentTime - bufferEnd < 2 * targetDuration) {
|
7952
|
-
|
8046
|
+
_this13.log("Cannot flush " + type + " front buffer while SourceBuffer is in ended state");
|
7953
8047
|
return;
|
7954
8048
|
}
|
7955
|
-
|
8049
|
+
_this13.hls.trigger(Events.BUFFER_FLUSHING, {
|
7956
8050
|
startOffset: bufferStart,
|
7957
8051
|
endOffset: Infinity,
|
7958
8052
|
type: type
|
@@ -7966,9 +8060,9 @@
|
|
7966
8060
|
* 'liveDurationInfinity` is set to `true`
|
7967
8061
|
* More details: https://github.com/video-dev/hls.js/issues/355
|
7968
8062
|
*/;
|
7969
|
-
_proto.
|
8063
|
+
_proto.getDurationAndRange = function getDurationAndRange() {
|
7970
8064
|
if (!this.details || !this.media || !this.mediaSource || this.mediaSource.readyState !== 'open') {
|
7971
|
-
return;
|
8065
|
+
return null;
|
7972
8066
|
}
|
7973
8067
|
var details = this.details,
|
7974
8068
|
hls = this.hls,
|
@@ -7980,25 +8074,40 @@
|
|
7980
8074
|
if (details.live && hls.config.liveDurationInfinity) {
|
7981
8075
|
// Override duration to Infinity
|
7982
8076
|
mediaSource.duration = Infinity;
|
7983
|
-
|
8077
|
+
var len = details.fragments.length;
|
8078
|
+
if (len && details.live && !!mediaSource.setLiveSeekableRange) {
|
8079
|
+
var start = Math.max(0, details.fragments[0].start);
|
8080
|
+
var end = Math.max(start, start + details.totalduration);
|
8081
|
+
return {
|
8082
|
+
duration: Infinity,
|
8083
|
+
start: start,
|
8084
|
+
end: end
|
8085
|
+
};
|
8086
|
+
}
|
8087
|
+
return {
|
8088
|
+
duration: Infinity
|
8089
|
+
};
|
7984
8090
|
} else if (levelDuration > msDuration && levelDuration > mediaDuration || !isFiniteNumber(mediaDuration)) {
|
7985
|
-
|
7986
|
-
|
7987
|
-
|
7988
|
-
// flushing already buffered portion when switching between quality level
|
7989
|
-
this.log("Updating Media Source duration to " + levelDuration.toFixed(3));
|
7990
|
-
mediaSource.duration = levelDuration;
|
8091
|
+
return {
|
8092
|
+
duration: levelDuration
|
8093
|
+
};
|
7991
8094
|
}
|
8095
|
+
return null;
|
7992
8096
|
};
|
7993
|
-
_proto.
|
7994
|
-
var
|
7995
|
-
|
7996
|
-
|
7997
|
-
if (
|
7998
|
-
|
7999
|
-
|
8000
|
-
|
8001
|
-
|
8097
|
+
_proto.updateMediaSource = function updateMediaSource(_ref2) {
|
8098
|
+
var duration = _ref2.duration,
|
8099
|
+
start = _ref2.start,
|
8100
|
+
end = _ref2.end;
|
8101
|
+
if (!this.media || !this.mediaSource || this.mediaSource.readyState !== 'open') {
|
8102
|
+
return;
|
8103
|
+
}
|
8104
|
+
if (isFiniteNumber(duration)) {
|
8105
|
+
this.log("Updating Media Source duration to " + duration.toFixed(3));
|
8106
|
+
}
|
8107
|
+
this.mediaSource.duration = duration;
|
8108
|
+
if (start !== undefined && end !== undefined) {
|
8109
|
+
this.log("Media Source duration is set to " + this.mediaSource.duration + ". Setting seekable range to " + start + "-" + end + ".");
|
8110
|
+
this.mediaSource.setLiveSeekableRange(start, end);
|
8002
8111
|
}
|
8003
8112
|
};
|
8004
8113
|
_proto.checkPendingTracks = function checkPendingTracks() {
|
@@ -8037,7 +8146,7 @@
|
|
8037
8146
|
}
|
8038
8147
|
};
|
8039
8148
|
_proto.createSourceBuffers = function createSourceBuffers(tracks) {
|
8040
|
-
var
|
8149
|
+
var _this14 = this;
|
8041
8150
|
var sourceBuffer = this.sourceBuffer,
|
8042
8151
|
mediaSource = this.mediaSource;
|
8043
8152
|
if (!mediaSource) {
|
@@ -8053,28 +8162,28 @@
|
|
8053
8162
|
var codec = track.levelCodec || track.codec;
|
8054
8163
|
if (codec) {
|
8055
8164
|
if (trackName.slice(0, 5) === 'audio') {
|
8056
|
-
codec = getCodecCompatibleName(codec,
|
8165
|
+
codec = getCodecCompatibleName(codec, _this14.hls.config.preferManagedMediaSource);
|
8057
8166
|
}
|
8058
8167
|
}
|
8059
8168
|
var mimeType = track.container + ";codecs=" + codec;
|
8060
|
-
|
8169
|
+
_this14.log("creating sourceBuffer(" + mimeType + ")");
|
8061
8170
|
try {
|
8062
8171
|
var sb = sourceBuffer[trackName] = mediaSource.addSourceBuffer(mimeType);
|
8063
8172
|
var sbName = trackName;
|
8064
|
-
|
8065
|
-
|
8066
|
-
|
8173
|
+
_this14.addBufferListener(sbName, 'updatestart', _this14._onSBUpdateStart);
|
8174
|
+
_this14.addBufferListener(sbName, 'updateend', _this14._onSBUpdateEnd);
|
8175
|
+
_this14.addBufferListener(sbName, 'error', _this14._onSBUpdateError);
|
8067
8176
|
// ManagedSourceBuffer bufferedchange event
|
8068
|
-
|
8177
|
+
_this14.addBufferListener(sbName, 'bufferedchange', function (type, event) {
|
8069
8178
|
// If media was ejected check for a change. Added ranges are redundant with changes on 'updateend' event.
|
8070
8179
|
var removedRanges = event.removedRanges;
|
8071
8180
|
if (removedRanges != null && removedRanges.length) {
|
8072
|
-
|
8181
|
+
_this14.hls.trigger(Events.BUFFER_FLUSHED, {
|
8073
8182
|
type: trackName
|
8074
8183
|
});
|
8075
8184
|
}
|
8076
8185
|
});
|
8077
|
-
|
8186
|
+
_this14.tracks[trackName] = {
|
8078
8187
|
buffer: sb,
|
8079
8188
|
codec: codec,
|
8080
8189
|
container: track.container,
|
@@ -8083,8 +8192,8 @@
|
|
8083
8192
|
id: track.id
|
8084
8193
|
};
|
8085
8194
|
} catch (err) {
|
8086
|
-
|
8087
|
-
|
8195
|
+
_this14.error("error while trying to add sourceBuffer: " + err.message);
|
8196
|
+
_this14.hls.trigger(Events.ERROR, {
|
8088
8197
|
type: ErrorTypes.MEDIA_ERROR,
|
8089
8198
|
details: ErrorDetails.BUFFER_ADD_CODEC_ERROR,
|
8090
8199
|
fatal: false,
|
@@ -8172,6 +8281,7 @@
|
|
8172
8281
|
}
|
8173
8282
|
return;
|
8174
8283
|
}
|
8284
|
+
sb.ending = false;
|
8175
8285
|
sb.ended = false;
|
8176
8286
|
sb.appendBuffer(data);
|
8177
8287
|
}
|
@@ -8181,7 +8291,7 @@
|
|
8181
8291
|
// upon completion, since we already do it here
|
8182
8292
|
;
|
8183
8293
|
_proto.blockBuffers = function blockBuffers(onUnblocked, buffers) {
|
8184
|
-
var
|
8294
|
+
var _this15 = this;
|
8185
8295
|
if (buffers === void 0) {
|
8186
8296
|
buffers = this.getSourceBufferTypes();
|
8187
8297
|
}
|
@@ -8196,11 +8306,15 @@
|
|
8196
8306
|
var blockingOperations = buffers.map(function (type) {
|
8197
8307
|
return operationQueue.appendBlocker(type);
|
8198
8308
|
});
|
8199
|
-
|
8309
|
+
var audioBlocked = buffers.length > 1 && !!this.blockedAudioAppend;
|
8310
|
+
if (audioBlocked) {
|
8311
|
+
this.unblockAudio();
|
8312
|
+
}
|
8313
|
+
Promise.all(blockingOperations).then(function (result) {
|
8200
8314
|
// logger.debug(`[buffer-controller]: Blocking operation resolved; unblocking ${buffers} SourceBuffer`);
|
8201
8315
|
onUnblocked();
|
8202
|
-
buffers.forEach(function (type) {
|
8203
|
-
var sb =
|
8316
|
+
buffers.forEach(function (type, i) {
|
8317
|
+
var sb = _this15.sourceBuffer[type];
|
8204
8318
|
// Only cycle the queue if the SB is not updating. There's a bug in Chrome which sets the SB updating flag to
|
8205
8319
|
// true when changing the MediaSource duration (https://bugs.chromium.org/p/chromium/issues/detail?id=959359&can=2&q=mediasource%20duration)
|
8206
8320
|
// While this is a workaround, it's probably useful to have around
|
@@ -10559,11 +10673,14 @@
|
|
10559
10673
|
* If not found any Fragment, return null
|
10560
10674
|
*/;
|
10561
10675
|
_proto.getBufferedFrag = function getBufferedFrag(position, levelType) {
|
10676
|
+
return this.getFragAtPos(position, levelType, true);
|
10677
|
+
};
|
10678
|
+
_proto.getFragAtPos = function getFragAtPos(position, levelType, buffered) {
|
10562
10679
|
var fragments = this.fragments;
|
10563
10680
|
var keys = Object.keys(fragments);
|
10564
10681
|
for (var i = keys.length; i--;) {
|
10565
10682
|
var fragmentEntity = fragments[keys[i]];
|
10566
|
-
if ((fragmentEntity == null ? void 0 : fragmentEntity.body.type) === levelType && fragmentEntity.buffered) {
|
10683
|
+
if ((fragmentEntity == null ? void 0 : fragmentEntity.body.type) === levelType && (!buffered || fragmentEntity.buffered)) {
|
10567
10684
|
var frag = fragmentEntity.body;
|
10568
10685
|
if (frag.start <= position && position <= frag.end) {
|
10569
10686
|
return frag;
|
@@ -10813,10 +10930,10 @@
|
|
10813
10930
|
};
|
10814
10931
|
};
|
10815
10932
|
_proto.onBufferAppended = function onBufferAppended(event, data) {
|
10816
|
-
var _this3 = this;
|
10817
10933
|
var frag = data.frag,
|
10818
10934
|
part = data.part,
|
10819
|
-
timeRanges = data.timeRanges
|
10935
|
+
timeRanges = data.timeRanges,
|
10936
|
+
type = data.type;
|
10820
10937
|
if (frag.sn === 'initSegment') {
|
10821
10938
|
return;
|
10822
10939
|
}
|
@@ -10830,10 +10947,8 @@
|
|
10830
10947
|
}
|
10831
10948
|
// Store the latest timeRanges loaded in the buffer
|
10832
10949
|
this.timeRanges = timeRanges;
|
10833
|
-
|
10834
|
-
|
10835
|
-
_this3.detectEvictedFragments(elementaryStream, timeRange, playlistType, part);
|
10836
|
-
});
|
10950
|
+
var timeRange = timeRanges[type];
|
10951
|
+
this.detectEvictedFragments(type, timeRange, playlistType, part);
|
10837
10952
|
};
|
10838
10953
|
_proto.onFragBuffered = function onFragBuffered(event, data) {
|
10839
10954
|
this.detectPartialFragments(data);
|
@@ -10847,12 +10962,12 @@
|
|
10847
10962
|
return !!((_this$activePartLists = this.activePartLists[type]) != null && _this$activePartLists.length);
|
10848
10963
|
};
|
10849
10964
|
_proto.removeFragmentsInRange = function removeFragmentsInRange(start, end, playlistType, withGapOnly, unbufferedOnly) {
|
10850
|
-
var
|
10965
|
+
var _this3 = this;
|
10851
10966
|
if (withGapOnly && !this.hasGaps) {
|
10852
10967
|
return;
|
10853
10968
|
}
|
10854
10969
|
Object.keys(this.fragments).forEach(function (key) {
|
10855
|
-
var fragmentEntity =
|
10970
|
+
var fragmentEntity = _this3.fragments[key];
|
10856
10971
|
if (!fragmentEntity) {
|
10857
10972
|
return;
|
10858
10973
|
}
|
@@ -10861,7 +10976,7 @@
|
|
10861
10976
|
return;
|
10862
10977
|
}
|
10863
10978
|
if (frag.start < end && frag.end > start && (fragmentEntity.buffered || unbufferedOnly)) {
|
10864
|
-
|
10979
|
+
_this3.removeFragment(frag);
|
10865
10980
|
}
|
10866
10981
|
});
|
10867
10982
|
};
|
@@ -13049,7 +13164,7 @@
|
|
13049
13164
|
// Workaround flaw in getting forward buffer when maxBufferHole is smaller than gap at current pos
|
13050
13165
|
if (bufferInfo.len === 0 && bufferInfo.nextStart !== undefined) {
|
13051
13166
|
var bufferedFragAtPos = this.fragmentTracker.getBufferedFrag(pos, type);
|
13052
|
-
if (bufferedFragAtPos && bufferInfo.nextStart
|
13167
|
+
if (bufferedFragAtPos && (bufferInfo.nextStart <= bufferedFragAtPos.end || bufferedFragAtPos.gap)) {
|
13053
13168
|
return BufferHelper.bufferInfo(bufferable, pos, Math.max(bufferInfo.nextStart, maxBufferHole));
|
13054
13169
|
}
|
13055
13170
|
}
|
@@ -20408,6 +20523,17 @@
|
|
20408
20523
|
}
|
20409
20524
|
};
|
20410
20525
|
_createClass(StreamController, [{
|
20526
|
+
key: "maxBufferLength",
|
20527
|
+
get: function get() {
|
20528
|
+
var levels = this.levels,
|
20529
|
+
level = this.level;
|
20530
|
+
var levelInfo = levels == null ? void 0 : levels[level];
|
20531
|
+
if (!levelInfo) {
|
20532
|
+
return this.config.maxBufferLength;
|
20533
|
+
}
|
20534
|
+
return this.getMaxBufferLength(levelInfo.maxBitrate);
|
20535
|
+
}
|
20536
|
+
}, {
|
20411
20537
|
key: "nextLevel",
|
20412
20538
|
get: function get() {
|
20413
20539
|
var frag = this.nextBufferedFrag;
|
@@ -20544,7 +20670,9 @@
|
|
20544
20670
|
ConfigFpsController = config.fpsController;
|
20545
20671
|
var errorController = new ConfigErrorController(this);
|
20546
20672
|
var abrController = this.abrController = new ConfigAbrController(this);
|
20547
|
-
|
20673
|
+
// FragmentTracker must be defined before StreamController because the order of event handling is important
|
20674
|
+
var fragmentTracker = new FragmentTracker(this);
|
20675
|
+
var bufferController = this.bufferController = new ConfigBufferController(this, fragmentTracker);
|
20548
20676
|
var capLevelController = this.capLevelController = new ConfigCapLevelController(this);
|
20549
20677
|
var fpsController = new ConfigFpsController(this);
|
20550
20678
|
var playListLoader = new PlaylistLoader(this);
|
@@ -20553,8 +20681,6 @@
|
|
20553
20681
|
// ConentSteeringController is defined before LevelController to receive Multivariant Playlist events first
|
20554
20682
|
var contentSteering = ConfigContentSteeringController ? new ConfigContentSteeringController(this) : null;
|
20555
20683
|
var levelController = this.levelController = new LevelController(this, contentSteering);
|
20556
|
-
// FragmentTracker must be defined before StreamController because the order of event handling is important
|
20557
|
-
var fragmentTracker = new FragmentTracker(this);
|
20558
20684
|
var keyLoader = new KeyLoader(this.config);
|
20559
20685
|
var streamController = this.streamController = new StreamController(this, fragmentTracker, keyLoader);
|
20560
20686
|
|
@@ -21151,6 +21277,11 @@
|
|
21151
21277
|
get: function get() {
|
21152
21278
|
return this.streamController.getMainFwdBufferInfo();
|
21153
21279
|
}
|
21280
|
+
}, {
|
21281
|
+
key: "maxBufferLength",
|
21282
|
+
get: function get() {
|
21283
|
+
return this.streamController.maxBufferLength;
|
21284
|
+
}
|
21154
21285
|
}, {
|
21155
21286
|
key: "allAudioTracks",
|
21156
21287
|
get: function get() {
|
@@ -21333,7 +21464,7 @@
|
|
21333
21464
|
* Get the video-dev/hls.js package version.
|
21334
21465
|
*/
|
21335
21466
|
function get() {
|
21336
|
-
return "1.5.7-0.canary.
|
21467
|
+
return "1.5.7-0.canary.10016";
|
21337
21468
|
}
|
21338
21469
|
}, {
|
21339
21470
|
key: "Events",
|