Skip to content

Commit 0a94f37

Browse files
committed
freeze: Fix typos and add constants
1 parent 30ad4f6 commit 0a94f37

File tree

2 files changed

+48
-9
lines changed

2 files changed

+48
-9
lines changed

src/core/main/common/FreezeResolver.ts

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,42 @@ import getMonotonicTimeStamp from "../../../utils/monotonic_timestamp";
1010
import type SegmentSinksStore from "../../segment_sinks";
1111
import type { IBufferedChunk } from "../../segment_sinks";
1212

13+
/**
14+
* "Freezing" is a complex situation indicating that playback is not advancing
15+
* despite no valid reason for it not to.
16+
*
17+
* Technically, there's multiple scenarios in which the RxPlayer will consider
18+
* the stream as "freezing" and try to fix it.
19+
* One of those scenarios is when there's a
20+
* `HTMLMediaElement.prototype.readyState` set to `1` (which is how the browser
21+
* tells us that it doesn't have any data to play), despite the fact that
22+
* there's actually data in the buffer.
23+
*
24+
* The `MINIMUM_BUFFER_GAP_AT_READY_STATE_1_BEFORE_FREEZING` is the minimum
25+
* buffer size in seconds after which we will suspect a "freezing" scenario if
26+
* the `readyState` is still at `1`.
27+
*/
28+
const MINIMUM_BUFFER_GAP_AT_READY_STATE_1_BEFORE_FREEZING = 6;
29+
30+
/**
31+
* To avoid handling freezes (e.g. "reloading" or "seeking") in a loop when
32+
* things go wrong, we have a security delay in milliseconds, this
33+
* `MINIMUM_TIME_BETWEEN_FREEZE_HANDLING` constant, which we'll await between
34+
* un-freezing attempts.
35+
*/
36+
const MINIMUM_TIME_BETWEEN_FREEZE_HANDLING = 6000;
37+
38+
/**
39+
* We maintain here a short-term history of what segments have been played
40+
* recently, to then implement heuristics detecting if a freeze was due to a
41+
* particular quality or track.
42+
*
43+
* To avoid growing that history indefinitely in size, we only save data
44+
* corresponding to the last `MAXIMUM_SEGMENT_HISTORY_RETENTION_TIME`
45+
* milliseconds from now.
46+
*/
47+
const MAXIMUM_SEGMENT_HISTORY_RETENTION_TIME = 60000;
48+
1349
/**
1450
* Set when there is a freeze which seems to be specifically linked to a,
1551
* or multiple, content's `Representation` despite no attribute of it
@@ -139,9 +175,9 @@ export default class FreezeResolver {
139175

140176
/**
141177
* Check that playback is not freezing, and if it is, return a solution that
142-
* should be atempted to unfreeze it.
178+
* should be attempted to unfreeze it.
143179
*
144-
* Returns `null` either when there's no freeze is happening or if there's one
180+
* Returns `null` either when there's no freeze happening or if there's one
145181
* but there's nothing we should do about it yet.
146182
*
147183
* Refer to the returned type's definition for more information.
@@ -178,7 +214,10 @@ export default class FreezeResolver {
178214
// playback. Yet, rebuffering occurences can also be abnormal, such as
179215
// when enough buffer is constructed but with a low readyState (those are
180216
// generally decryption issues).
181-
(rebuffering !== null && readyState === 1 && (bufferGap >= 6 || fullyLoaded));
217+
(rebuffering !== null &&
218+
readyState === 1 &&
219+
(bufferGap >= MINIMUM_BUFFER_GAP_AT_READY_STATE_1_BEFORE_FREEZING ||
220+
fullyLoaded));
182221

183222
if (!isFrozen) {
184223
this._decipherabilityFreezeStartingTimestamp = null;
@@ -202,7 +241,7 @@ export default class FreezeResolver {
202241
if (recentFlushAttemptFailed) {
203242
const secondUnfreezeStrat = this._getStrategyIfFlushingFails(freezingPosition);
204243
this._decipherabilityFreezeStartingTimestamp = null;
205-
this._ignoreFreezeUntil = now + 6000;
244+
this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
206245
return secondUnfreezeStrat;
207246
}
208247

@@ -222,7 +261,7 @@ export default class FreezeResolver {
222261
log.debug("FR: trying to flush to un-freeze");
223262

224263
this._decipherabilityFreezeStartingTimestamp = null;
225-
this._ignoreFreezeUntil = now + 6000;
264+
this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
226265
return {
227266
type: "flush",
228267
value: { relativeSeek: UNFREEZING_DELTA_POSITION },
@@ -280,7 +319,7 @@ export default class FreezeResolver {
280319
if (representation.decipherable === false) {
281320
log.warn("FR: we have undecipherable segments left in the buffer, reloading");
282321
this._decipherabilityFreezeStartingTimestamp = null;
283-
this._ignoreFreezeUntil = now + 6000;
322+
this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
284323
return { type: "reload", value: null };
285324
} else if (representation.contentProtections !== undefined) {
286325
isClear = false;
@@ -298,7 +337,7 @@ export default class FreezeResolver {
298337
"segments left in the buffer, reloading",
299338
);
300339
this._decipherabilityFreezeStartingTimestamp = null;
301-
this._ignoreFreezeUntil = now + 6000;
340+
this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
302341
return { type: "reload", value: null };
303342
}
304343
return null;
@@ -459,7 +498,7 @@ export default class FreezeResolver {
459498
this._lastSegmentInfo[ttype].splice(0, toRemove);
460499
}
461500

462-
const removalTs = currentTimestamp - 60000;
501+
const removalTs = currentTimestamp - MAXIMUM_SEGMENT_HISTORY_RETENTION_TIME;
463502
let i;
464503
for (i = 0; i < this._lastSegmentInfo[ttype].length; i++) {
465504
if (this._lastSegmentInfo[ttype][i].timestamp > removalTs) {

src/core/main/worker/worker_main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ function loadOrReloadPreparedContent(
891891
);
892892
contentPreparer.reloadMediaSource(payload).then(
893893
() => {
894-
log.info("WP: MediaSource Reloaded, loading...");
894+
log.info("WP: MediaSource Reloaded, loading content again");
895895
loadOrReloadPreparedContent(
896896
{
897897
initialTime: newInitialTime,

0 commit comments

Comments
 (0)