mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-28 19:06:52 +03:00
fix auto quality recovery after a downswitch
The downswitch callback armed the upswitch probe, but `triggerDownswitch` reset the stall history right after the callback returned, which disarmed it again. Auto quality stayed on the sub stream until the next chunk boundary no matter how much the connection recovered. The governor now arms the probe itself after the reset. The chunk boundary effect also ran on mount, so when coverage was already cached it immediately undid the low quality cold start the seed effect had just picked. It now only runs when the chunk actually changes.
This commit is contained in:
@@ -340,8 +340,11 @@ export class AutoQualityGovernor {
|
||||
private triggerDownswitch(reason: DownswitchReason): boolean {
|
||||
const handled = this.requestDownswitch(reason);
|
||||
if (handled) {
|
||||
// the low stream starts with a clean record
|
||||
// the low stream starts with a clean record, and the probe lets a
|
||||
// recovered connection (or a wrong downswitch) return to full
|
||||
// quality mid-chunk rather than at the next boundary
|
||||
this.resetStallHistory();
|
||||
this.armUpswitchProbe();
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
@@ -484,9 +484,6 @@ export default function DynamicVideoPlayer({
|
||||
}
|
||||
setAutoLowQuality(true);
|
||||
setAutoLowReason(reason === "codec" ? "codec" : "bandwidth");
|
||||
// so a recovered connection (or a wrong downswitch) returns to
|
||||
// full quality mid-chunk rather than at the next boundary
|
||||
governor.armUpswitchProbe();
|
||||
return true;
|
||||
};
|
||||
tryUpswitchRef.current = () => {
|
||||
@@ -495,7 +492,7 @@ export default function DynamicVideoPlayer({
|
||||
setAutoLowReason(undefined);
|
||||
}
|
||||
};
|
||||
}, [resolvedQuality, subAvailable, governor]);
|
||||
}, [resolvedQuality, subAvailable]);
|
||||
|
||||
// persisted across sessions so a device on a known-slow connection
|
||||
// starts low instead of paying the first stall to find out
|
||||
@@ -616,7 +613,19 @@ export default function DynamicVideoPlayer({
|
||||
governor.sourceLoadStarted();
|
||||
}, [source, isScrubbing, governor]);
|
||||
|
||||
const lastChunkRef = useRef(timeRange);
|
||||
useEffect(() => {
|
||||
// the seed effect picks the starting quality, so only a later chunk
|
||||
// boundary reconsiders it
|
||||
const lastChunk = lastChunkRef.current;
|
||||
lastChunkRef.current = timeRange;
|
||||
if (
|
||||
lastChunk.after === timeRange.after &&
|
||||
lastChunk.before === timeRange.before
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// a chunk boundary is where full quality may be retried, and a
|
||||
// natural point to persist what the governor has learned
|
||||
setAutoLowQuality((prev) => prev && !governor.shouldRetryMain());
|
||||
|
||||
Reference in New Issue
Block a user