hls.js 1.6.0-beta.2.0.canary.10882 → 1.6.0-beta.2.0.canary.10883
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.d.mts +21 -0
- package/dist/hls.d.ts +21 -0
- package/dist/hls.js +109 -64
- package/dist/hls.js.d.ts +21 -0
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +109 -64
- 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 +106 -63
- 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 +106 -63
- 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/config.ts +2 -0
- package/src/controller/gap-controller.ts +92 -58
- package/src/controller/stream-controller.ts +13 -3
- package/src/events.ts +3 -0
- package/src/hls.ts +2 -1
- package/src/types/events.ts +3 -0
- package/src/utils/buffer-helper.ts +5 -8
package/dist/hls.mjs
CHANGED
@@ -77,6 +77,7 @@ let Events = /*#__PURE__*/function (Events) {
|
|
77
77
|
Events["MEDIA_DETACHING"] = "hlsMediaDetaching";
|
78
78
|
Events["MEDIA_DETACHED"] = "hlsMediaDetached";
|
79
79
|
Events["MEDIA_ENDED"] = "hlsMediaEnded";
|
80
|
+
Events["STALL_RESOLVED"] = "hlsStallResolved";
|
80
81
|
Events["BUFFER_RESET"] = "hlsBufferReset";
|
81
82
|
Events["BUFFER_CODECS"] = "hlsBufferCodecs";
|
82
83
|
Events["BUFFER_CREATED"] = "hlsBufferCreated";
|
@@ -401,7 +402,7 @@ function enableLogs(debugConfig, context, id) {
|
|
401
402
|
// Some browsers don't allow to use bind on console object anyway
|
402
403
|
// fallback to default if needed
|
403
404
|
try {
|
404
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.2.0.canary.
|
405
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.0-beta.2.0.canary.10883"}`);
|
405
406
|
} catch (e) {
|
406
407
|
/* log fn threw an exception. All logger methods are no-ops. */
|
407
408
|
return createLogger();
|
@@ -5862,8 +5863,7 @@ class BufferHelper {
|
|
5862
5863
|
return {
|
5863
5864
|
len: 0,
|
5864
5865
|
start: pos,
|
5865
|
-
end: pos
|
5866
|
-
nextStart: undefined
|
5866
|
+
end: pos
|
5867
5867
|
};
|
5868
5868
|
}
|
5869
5869
|
static bufferedInfo(buffered, pos, maxHoleDuration) {
|
@@ -5926,7 +5926,8 @@ class BufferHelper {
|
|
5926
5926
|
len: bufferLen,
|
5927
5927
|
start: bufferStart || 0,
|
5928
5928
|
end: bufferEnd || 0,
|
5929
|
-
nextStart: bufferStartNext
|
5929
|
+
nextStart: bufferStartNext,
|
5930
|
+
buffered
|
5930
5931
|
};
|
5931
5932
|
}
|
5932
5933
|
|
@@ -9847,7 +9848,7 @@ var eventemitter3 = {exports: {}};
|
|
9847
9848
|
var eventemitter3Exports = eventemitter3.exports;
|
9848
9849
|
var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
|
9849
9850
|
|
9850
|
-
const version = "1.6.0-beta.2.0.canary.
|
9851
|
+
const version = "1.6.0-beta.2.0.canary.10883";
|
9851
9852
|
|
9852
9853
|
// ensure the worker ends up in the bundle
|
9853
9854
|
// If the worker should not be included this gets aliased to empty.js
|
@@ -29443,6 +29444,7 @@ const hlsDefaultConfig = _objectSpread2(_objectSpread2({
|
|
29443
29444
|
progressive: false,
|
29444
29445
|
lowLatencyMode: true,
|
29445
29446
|
cmcd: undefined,
|
29447
|
+
detectStallWithCurrentTimeMs: 1250,
|
29446
29448
|
enableDateRangeMetadataCues: true,
|
29447
29449
|
enableEmsgMetadataCues: true,
|
29448
29450
|
enableEmsgKLVMetadata: false,
|
@@ -30851,32 +30853,28 @@ function assignTrackIdsByGroup(tracks) {
|
|
30851
30853
|
});
|
30852
30854
|
}
|
30853
30855
|
|
30854
|
-
const STALL_MINIMUM_DURATION_MS = 250;
|
30855
30856
|
const MAX_START_GAP_JUMP = 2.0;
|
30856
30857
|
const SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
|
30857
30858
|
const SKIP_BUFFER_RANGE_START = 0.05;
|
30858
30859
|
class GapController extends Logger {
|
30859
|
-
constructor(
|
30860
|
+
constructor(media, fragmentTracker, hls) {
|
30860
30861
|
super('gap-controller', hls.logger);
|
30861
|
-
this.config = undefined;
|
30862
30862
|
this.media = null;
|
30863
|
-
this.fragmentTracker =
|
30864
|
-
this.hls =
|
30863
|
+
this.fragmentTracker = null;
|
30864
|
+
this.hls = null;
|
30865
30865
|
this.nudgeRetry = 0;
|
30866
30866
|
this.stallReported = false;
|
30867
30867
|
this.stalled = null;
|
30868
30868
|
this.moved = false;
|
30869
30869
|
this.seeking = false;
|
30870
30870
|
this.ended = 0;
|
30871
|
-
this.
|
30871
|
+
this.waiting = 0;
|
30872
30872
|
this.media = media;
|
30873
30873
|
this.fragmentTracker = fragmentTracker;
|
30874
30874
|
this.hls = hls;
|
30875
30875
|
}
|
30876
30876
|
destroy() {
|
30877
|
-
this.media = null;
|
30878
|
-
// @ts-ignore
|
30879
|
-
this.hls = this.fragmentTracker = null;
|
30877
|
+
this.media = this.hls = this.fragmentTracker = null;
|
30880
30878
|
}
|
30881
30879
|
|
30882
30880
|
/**
|
@@ -30886,12 +30884,12 @@ class GapController extends Logger {
|
|
30886
30884
|
* @param lastCurrentTime - Previously read playhead position
|
30887
30885
|
*/
|
30888
30886
|
poll(lastCurrentTime, activeFrag, levelDetails, state) {
|
30887
|
+
var _this$hls;
|
30889
30888
|
const {
|
30890
|
-
config,
|
30891
30889
|
media,
|
30892
30890
|
stalled
|
30893
30891
|
} = this;
|
30894
|
-
if (media
|
30892
|
+
if (!media) {
|
30895
30893
|
return;
|
30896
30894
|
}
|
30897
30895
|
const {
|
@@ -30911,43 +30909,45 @@ class GapController extends Logger {
|
|
30911
30909
|
if (!seeking) {
|
30912
30910
|
this.nudgeRetry = 0;
|
30913
30911
|
}
|
30914
|
-
if (
|
30915
|
-
|
30916
|
-
if (this.stallReported) {
|
30917
|
-
const _stalledDuration = self.performance.now() - stalled;
|
30918
|
-
this.warn(`playback not stuck anymore @${currentTime}, after ${Math.round(_stalledDuration)}ms`);
|
30919
|
-
this.stallReported = false;
|
30920
|
-
}
|
30921
|
-
this.stalled = null;
|
30912
|
+
if (this.waiting === 0) {
|
30913
|
+
this.stallResolved(currentTime);
|
30922
30914
|
}
|
30923
30915
|
return;
|
30924
30916
|
}
|
30925
30917
|
|
30926
30918
|
// Clear stalled state when beginning or finishing seeking so that we don't report stalls coming out of a seek
|
30927
30919
|
if (beginSeek || seeked) {
|
30928
|
-
|
30920
|
+
if (seeked) {
|
30921
|
+
this.stallResolved(currentTime);
|
30922
|
+
}
|
30929
30923
|
return;
|
30930
30924
|
}
|
30931
30925
|
|
30932
30926
|
// The playhead should not be moving
|
30933
|
-
if (media.paused && !seeking || media.ended || media.playbackRate === 0
|
30927
|
+
if (media.paused && !seeking || media.ended || media.playbackRate === 0) {
|
30928
|
+
this.nudgeRetry = 0;
|
30929
|
+
this.stallResolved(currentTime);
|
30934
30930
|
// Fire MEDIA_ENDED to workaround event not being dispatched by browser
|
30935
|
-
if (!this.ended && media.ended) {
|
30931
|
+
if (!this.ended && media.ended && this.hls) {
|
30936
30932
|
this.ended = currentTime || 1;
|
30937
30933
|
this.hls.trigger(Events.MEDIA_ENDED, {
|
30938
30934
|
stalled: false
|
30939
30935
|
});
|
30940
30936
|
}
|
30937
|
+
return;
|
30938
|
+
}
|
30939
|
+
if (!BufferHelper.getBuffered(media).length) {
|
30941
30940
|
this.nudgeRetry = 0;
|
30942
30941
|
return;
|
30943
30942
|
}
|
30944
30943
|
const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);
|
30945
30944
|
const nextStart = bufferInfo.nextStart || 0;
|
30946
|
-
|
30945
|
+
const fragmentTracker = this.fragmentTracker;
|
30946
|
+
if (seeking && fragmentTracker) {
|
30947
30947
|
// Waiting for seeking in a buffered range to complete
|
30948
30948
|
const hasEnoughBuffer = bufferInfo.len > MAX_START_GAP_JUMP;
|
30949
30949
|
// Next buffered range is too far ahead to jump to while still seeking
|
30950
|
-
const noBufferGap = !nextStart || activeFrag && activeFrag.start <= currentTime || nextStart - currentTime > MAX_START_GAP_JUMP && !
|
30950
|
+
const noBufferGap = !nextStart || activeFrag && activeFrag.start <= currentTime || nextStart - currentTime > MAX_START_GAP_JUMP && !fragmentTracker.getPartialFragment(currentTime);
|
30951
30951
|
if (hasEnoughBuffer || noBufferGap) {
|
30952
30952
|
return;
|
30953
30953
|
}
|
@@ -30957,7 +30957,7 @@ class GapController extends Logger {
|
|
30957
30957
|
|
30958
30958
|
// Skip start gaps if we haven't played, but the last poll detected the start of a stall
|
30959
30959
|
// The addition poll gives the browser a chance to jump the gap for us
|
30960
|
-
if (!this.moved && this.stalled !== null) {
|
30960
|
+
if (!this.moved && this.stalled !== null && fragmentTracker) {
|
30961
30961
|
// There is no playable buffer (seeked, waiting for buffer)
|
30962
30962
|
const isBuffered = bufferInfo.len > 0;
|
30963
30963
|
if (!isBuffered && !nextStart) {
|
@@ -30971,7 +30971,7 @@ class GapController extends Logger {
|
|
30971
30971
|
// that begins over 1 target duration after the video start position.
|
30972
30972
|
const isLive = !!(levelDetails != null && levelDetails.live);
|
30973
30973
|
const maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
|
30974
|
-
const partialOrGap =
|
30974
|
+
const partialOrGap = fragmentTracker.getPartialFragment(currentTime);
|
30975
30975
|
if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
|
30976
30976
|
if (!media.paused) {
|
30977
30977
|
this._trySkipBufferHole(partialOrGap);
|
@@ -30981,16 +30981,27 @@ class GapController extends Logger {
|
|
30981
30981
|
}
|
30982
30982
|
|
30983
30983
|
// Start tracking stall time
|
30984
|
+
const config = (_this$hls = this.hls) == null ? undefined : _this$hls.config;
|
30985
|
+
if (!config) {
|
30986
|
+
return;
|
30987
|
+
}
|
30988
|
+
const detectStallWithCurrentTimeMs = config.detectStallWithCurrentTimeMs;
|
30984
30989
|
const tnow = self.performance.now();
|
30990
|
+
const tWaiting = this.waiting;
|
30985
30991
|
if (stalled === null) {
|
30986
|
-
|
30992
|
+
// Use time of recent "waiting" event
|
30993
|
+
if (tWaiting > 0 && tnow - tWaiting < detectStallWithCurrentTimeMs) {
|
30994
|
+
this.stalled = tWaiting;
|
30995
|
+
} else {
|
30996
|
+
this.stalled = tnow;
|
30997
|
+
}
|
30987
30998
|
return;
|
30988
30999
|
}
|
30989
31000
|
const stalledDuration = tnow - stalled;
|
30990
|
-
if (!seeking && stalledDuration >=
|
31001
|
+
if (!seeking && (stalledDuration >= detectStallWithCurrentTimeMs || tWaiting) && this.hls) {
|
30991
31002
|
// Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
|
30992
31003
|
if (state === State.ENDED && !(levelDetails != null && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? undefined : levelDetails.edge) || 0)) < 1) {
|
30993
|
-
if (
|
31004
|
+
if (this.ended) {
|
30994
31005
|
return;
|
30995
31006
|
}
|
30996
31007
|
this.ended = currentTime || 1;
|
@@ -31001,13 +31012,27 @@ class GapController extends Logger {
|
|
31001
31012
|
}
|
31002
31013
|
// Report stalling after trying to fix
|
31003
31014
|
this._reportStall(bufferInfo);
|
31004
|
-
if (!this.media) {
|
31015
|
+
if (!this.media || !this.hls) {
|
31005
31016
|
return;
|
31006
31017
|
}
|
31007
31018
|
}
|
31008
31019
|
const bufferedWithHoles = BufferHelper.bufferInfo(media, currentTime, config.maxBufferHole);
|
31009
31020
|
this._tryFixBufferStall(bufferedWithHoles, stalledDuration);
|
31010
31021
|
}
|
31022
|
+
stallResolved(currentTime) {
|
31023
|
+
const stalled = this.stalled;
|
31024
|
+
if (stalled && this.hls) {
|
31025
|
+
this.stalled = null;
|
31026
|
+
// The playhead is now moving, but was previously stalled
|
31027
|
+
if (this.stallReported) {
|
31028
|
+
const stalledDuration = self.performance.now() - stalled;
|
31029
|
+
this.warn(`playback not stuck anymore @${currentTime}, after ${Math.round(stalledDuration)}ms`);
|
31030
|
+
this.stallReported = false;
|
31031
|
+
this.waiting = 0;
|
31032
|
+
this.hls.trigger(Events.STALL_RESOLVED, {});
|
31033
|
+
}
|
31034
|
+
}
|
31035
|
+
}
|
31011
31036
|
|
31012
31037
|
/**
|
31013
31038
|
* Detects and attempts to fix known buffer stalling issues.
|
@@ -31016,12 +31041,13 @@ class GapController extends Logger {
|
|
31016
31041
|
* @private
|
31017
31042
|
*/
|
31018
31043
|
_tryFixBufferStall(bufferInfo, stalledDurationMs) {
|
31044
|
+
var _this$hls2;
|
31019
31045
|
const {
|
31020
|
-
config,
|
31021
31046
|
fragmentTracker,
|
31022
31047
|
media
|
31023
31048
|
} = this;
|
31024
|
-
|
31049
|
+
const config = (_this$hls2 = this.hls) == null ? undefined : _this$hls2.config;
|
31050
|
+
if (!media || !fragmentTracker || !config) {
|
31025
31051
|
return;
|
31026
31052
|
}
|
31027
31053
|
const currentTime = media.currentTime;
|
@@ -31041,13 +31067,12 @@ class GapController extends Logger {
|
|
31041
31067
|
// we may just have to "nudge" the playlist as the browser decoding/rendering engine
|
31042
31068
|
// needs to cross some sort of threshold covering all source-buffers content
|
31043
31069
|
// to start playing properly.
|
31044
|
-
|
31070
|
+
const bufferedRanges = bufferInfo.buffered;
|
31071
|
+
if ((bufferedRanges && bufferedRanges.length > 1 && bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
|
31045
31072
|
this.warn('Trying to nudge playhead over buffer-hole');
|
31046
31073
|
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
|
31047
31074
|
// We only try to jump the hole if it's under the configured size
|
31048
|
-
|
31049
|
-
this.stalled = null;
|
31050
|
-
this._tryNudgeBuffer();
|
31075
|
+
this._tryNudgeBuffer(bufferInfo);
|
31051
31076
|
}
|
31052
31077
|
}
|
31053
31078
|
|
@@ -31060,9 +31085,10 @@ class GapController extends Logger {
|
|
31060
31085
|
const {
|
31061
31086
|
hls,
|
31062
31087
|
media,
|
31063
|
-
stallReported
|
31088
|
+
stallReported,
|
31089
|
+
stalled
|
31064
31090
|
} = this;
|
31065
|
-
if (!stallReported && media) {
|
31091
|
+
if (!stallReported && stalled !== null && media && hls) {
|
31066
31092
|
// Report stalled error once
|
31067
31093
|
this.stallReported = true;
|
31068
31094
|
const error = new Error(`Playback stalling at @${media.currentTime} due to low buffer (${JSON.stringify(bufferInfo)})`);
|
@@ -31072,7 +31098,11 @@ class GapController extends Logger {
|
|
31072
31098
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
31073
31099
|
fatal: false,
|
31074
31100
|
error,
|
31075
|
-
buffer: bufferInfo.len
|
31101
|
+
buffer: bufferInfo.len,
|
31102
|
+
bufferInfo,
|
31103
|
+
stalled: {
|
31104
|
+
start: stalled
|
31105
|
+
}
|
31076
31106
|
});
|
31077
31107
|
}
|
31078
31108
|
}
|
@@ -31083,12 +31113,13 @@ class GapController extends Logger {
|
|
31083
31113
|
* @private
|
31084
31114
|
*/
|
31085
31115
|
_trySkipBufferHole(partial) {
|
31116
|
+
var _this$hls3;
|
31086
31117
|
const {
|
31087
|
-
|
31088
|
-
hls,
|
31118
|
+
fragmentTracker,
|
31089
31119
|
media
|
31090
31120
|
} = this;
|
31091
|
-
|
31121
|
+
const config = (_this$hls3 = this.hls) == null ? undefined : _this$hls3.config;
|
31122
|
+
if (!media || !fragmentTracker || !config) {
|
31092
31123
|
return 0;
|
31093
31124
|
}
|
31094
31125
|
|
@@ -31103,9 +31134,6 @@ class GapController extends Logger {
|
|
31103
31134
|
if (gapLength > 0 && (bufferStarved || waiting)) {
|
31104
31135
|
// Only allow large gaps to be skipped if it is a start gap, or all fragments in skip range are partial
|
31105
31136
|
if (gapLength > config.maxBufferHole) {
|
31106
|
-
const {
|
31107
|
-
fragmentTracker
|
31108
|
-
} = this;
|
31109
31137
|
let startGap = false;
|
31110
31138
|
if (currentTime === 0) {
|
31111
31139
|
const startFrag = fragmentTracker.getAppendedFrag(0, PlaylistLevelType.MAIN);
|
@@ -31136,17 +31164,18 @@ class GapController extends Logger {
|
|
31136
31164
|
const targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
|
31137
31165
|
this.warn(`skipping hole, adjusting currentTime from ${currentTime} to ${targetTime}`);
|
31138
31166
|
this.moved = true;
|
31139
|
-
this.stalled = null;
|
31140
31167
|
media.currentTime = targetTime;
|
31141
|
-
if (partial && !partial.gap) {
|
31168
|
+
if (partial && !partial.gap && this.hls) {
|
31142
31169
|
const error = new Error(`fragment loaded with buffer holes, seeking from ${currentTime} to ${targetTime}`);
|
31143
|
-
hls.trigger(Events.ERROR, {
|
31170
|
+
this.hls.trigger(Events.ERROR, {
|
31144
31171
|
type: ErrorTypes.MEDIA_ERROR,
|
31145
31172
|
details: ErrorDetails.BUFFER_SEEK_OVER_HOLE,
|
31146
31173
|
fatal: false,
|
31147
31174
|
error,
|
31148
31175
|
reason: error.message,
|
31149
|
-
frag: partial
|
31176
|
+
frag: partial,
|
31177
|
+
buffer: bufferInfo.len,
|
31178
|
+
bufferInfo
|
31150
31179
|
});
|
31151
31180
|
}
|
31152
31181
|
return targetTime;
|
@@ -31159,15 +31188,15 @@ class GapController extends Logger {
|
|
31159
31188
|
* Attempts to fix buffer stalls by advancing the mediaElement's current time by a small amount.
|
31160
31189
|
* @private
|
31161
31190
|
*/
|
31162
|
-
_tryNudgeBuffer() {
|
31191
|
+
_tryNudgeBuffer(bufferInfo) {
|
31163
31192
|
const {
|
31164
|
-
config,
|
31165
31193
|
hls,
|
31166
31194
|
media,
|
31167
31195
|
nudgeRetry
|
31168
31196
|
} = this;
|
31169
|
-
|
31170
|
-
|
31197
|
+
const config = hls == null ? undefined : hls.config;
|
31198
|
+
if (!media || !config) {
|
31199
|
+
return 0;
|
31171
31200
|
}
|
31172
31201
|
const currentTime = media.currentTime;
|
31173
31202
|
this.nudgeRetry++;
|
@@ -31181,7 +31210,9 @@ class GapController extends Logger {
|
|
31181
31210
|
type: ErrorTypes.MEDIA_ERROR,
|
31182
31211
|
details: ErrorDetails.BUFFER_NUDGE_ON_STALL,
|
31183
31212
|
error,
|
31184
|
-
fatal: false
|
31213
|
+
fatal: false,
|
31214
|
+
buffer: bufferInfo.len,
|
31215
|
+
bufferInfo
|
31185
31216
|
});
|
31186
31217
|
} else {
|
31187
31218
|
const error = new Error(`Playhead still not moving while enough data buffered @${currentTime} after ${config.nudgeMaxRetry} nudges`);
|
@@ -31190,7 +31221,9 @@ class GapController extends Logger {
|
|
31190
31221
|
type: ErrorTypes.MEDIA_ERROR,
|
31191
31222
|
details: ErrorDetails.BUFFER_STALLED_ERROR,
|
31192
31223
|
error,
|
31193
|
-
fatal: true
|
31224
|
+
fatal: true,
|
31225
|
+
buffer: bufferInfo.len,
|
31226
|
+
bufferInfo
|
31194
31227
|
});
|
31195
31228
|
}
|
31196
31229
|
}
|
@@ -31241,11 +31274,18 @@ class StreamController extends BaseStreamController {
|
|
31241
31274
|
this.backtrackFragment = null;
|
31242
31275
|
this.audioCodecSwitch = false;
|
31243
31276
|
this.videoBuffer = null;
|
31277
|
+
this.onMediaWaiting = () => {
|
31278
|
+
const gapController = this.gapController;
|
31279
|
+
if (gapController) {
|
31280
|
+
gapController.waiting = self.performance.now();
|
31281
|
+
}
|
31282
|
+
};
|
31244
31283
|
this.onMediaPlaying = () => {
|
31245
31284
|
// tick to speed up FRAG_CHANGED triggering
|
31246
31285
|
const gapController = this.gapController;
|
31247
31286
|
if (gapController) {
|
31248
31287
|
gapController.ended = 0;
|
31288
|
+
gapController.waiting = 0;
|
31249
31289
|
}
|
31250
31290
|
this.tick();
|
31251
31291
|
};
|
@@ -31301,7 +31341,7 @@ class StreamController extends BaseStreamController {
|
|
31301
31341
|
}
|
31302
31342
|
onHandlerDestroying() {
|
31303
31343
|
// @ts-ignore
|
31304
|
-
this.onMediaPlaying = this.onMediaSeeked = null;
|
31344
|
+
this.onMediaPlaying = this.onMediaSeeked = this.onMediaWaiting = null;
|
31305
31345
|
this.unregisterListeners();
|
31306
31346
|
super.onHandlerDestroying();
|
31307
31347
|
}
|
@@ -31632,9 +31672,11 @@ class StreamController extends BaseStreamController {
|
|
31632
31672
|
const media = data.media;
|
31633
31673
|
media.removeEventListener('playing', this.onMediaPlaying);
|
31634
31674
|
media.removeEventListener('seeked', this.onMediaSeeked);
|
31675
|
+
media.removeEventListener('waiting', this.onMediaWaiting);
|
31635
31676
|
media.addEventListener('playing', this.onMediaPlaying);
|
31636
31677
|
media.addEventListener('seeked', this.onMediaSeeked);
|
31637
|
-
|
31678
|
+
media.addEventListener('waiting', this.onMediaWaiting);
|
31679
|
+
this.gapController = new GapController(media, this.fragmentTracker, this.hls);
|
31638
31680
|
}
|
31639
31681
|
onMediaDetaching(event, data) {
|
31640
31682
|
const {
|
@@ -31643,6 +31685,7 @@ class StreamController extends BaseStreamController {
|
|
31643
31685
|
if (media) {
|
31644
31686
|
media.removeEventListener('playing', this.onMediaPlaying);
|
31645
31687
|
media.removeEventListener('seeked', this.onMediaSeeked);
|
31688
|
+
media.removeEventListener('waiting', this.onMediaWaiting);
|
31646
31689
|
}
|
31647
31690
|
this.videoBuffer = null;
|
31648
31691
|
this.fragPlaying = null;
|
@@ -32070,7 +32113,7 @@ class StreamController extends BaseStreamController {
|
|
32070
32113
|
let startPosition = this.startPosition;
|
32071
32114
|
// only adjust currentTime if different from startPosition or if startPosition not buffered
|
32072
32115
|
// at that stage, there should be only one buffered range, as we reach that code after first fragment has been buffered
|
32073
|
-
if (startPosition >= 0) {
|
32116
|
+
if (startPosition >= 0 && currentTime < startPosition) {
|
32074
32117
|
if (media.seeking) {
|
32075
32118
|
this.log(`could not seek to ${startPosition}, already seeking at ${currentTime}`);
|
32076
32119
|
return;
|