From c3f34753c6d64cd384c042e3e45a70c2108089bc Mon Sep 17 00:00:00 2001 From: KingKDot Date: Sun, 7 Jun 2026 00:05:35 -0500 Subject: [PATCH] fix fps toggle --- .../cmd/agent/capture/capture_test.go | 26 +++++++++++++ .../cmd/agent/capture/flowcontrol.go | 38 ++++++++++++++++++- Overlord-Client/cmd/agent/handlers/desktop.go | 3 ++ .../public/assets/remotedesktop.js | 1 + 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/Overlord-Client/cmd/agent/capture/capture_test.go b/Overlord-Client/cmd/agent/capture/capture_test.go index fba6d4e..f3b20b9 100644 --- a/Overlord-Client/cmd/agent/capture/capture_test.go +++ b/Overlord-Client/cmd/agent/capture/capture_test.go @@ -432,3 +432,29 @@ func TestCaptureAndSend_CancelledContext(t *testing.T) { // SHOULD handle gracefully, may or may not send depending on timing :sob: _ = CaptureAndSend(ctx, env) } + +func TestSetFrameFlowTargetFPSScalesHighFPS(t *testing.T) { + t.Setenv("OVERLORD_DESKTOP_IN_FLIGHT_FRAMES", "") + ResetFrameSlots() + SetFrameFlowTargetFPS(60) + if got := activeFrameSlotLimit(); got != 2 { + t.Fatalf("expected 60 fps slot limit 2, got %d", got) + } + SetFrameFlowTargetFPS(120) + if got := activeFrameSlotLimit(); got != 4 { + t.Fatalf("expected 120 fps slot limit 4, got %d", got) + } + SetFrameFlowTargetFPS(240) + if got := activeFrameSlotLimit(); got != 8 { + t.Fatalf("expected 240 fps slot limit 8, got %d", got) + } +} + +func TestSetFrameFlowTargetFPSEnvOverride(t *testing.T) { + t.Setenv("OVERLORD_DESKTOP_IN_FLIGHT_FRAMES", "12") + ResetFrameSlots() + SetFrameFlowTargetFPS(240) + if got := activeFrameSlotLimit(); got != 12 { + t.Fatalf("expected env slot limit 12, got %d", got) + } +} diff --git a/Overlord-Client/cmd/agent/capture/flowcontrol.go b/Overlord-Client/cmd/agent/capture/flowcontrol.go index 4a58737..0735acb 100644 --- a/Overlord-Client/cmd/agent/capture/flowcontrol.go +++ b/Overlord-Client/cmd/agent/capture/flowcontrol.go @@ -1,16 +1,20 @@ package capture import ( + "os" + "strconv" + "strings" "sync/atomic" "time" ) -const maxInFlightFrames int64 = 2 +const defaultMaxInFlightFrames int64 = 2 var ( inFlightFrames atomic.Int64 frameAckSeen atomic.Bool lastAckNano atomic.Int64 + maxFrameSlots atomic.Int64 ) func AcquireFrameSlot() bool { @@ -20,7 +24,7 @@ func AcquireFrameSlot() bool { for { cur := inFlightFrames.Load() - if cur >= maxInFlightFrames { + if cur >= activeFrameSlotLimit() { lastAck := lastAckNano.Load() if lastAck > 0 && time.Since(time.Unix(0, lastAck)) > time.Second { inFlightFrames.Store(0) @@ -47,3 +51,33 @@ func ResetFrameSlots() { frameAckSeen.Store(false) lastAckNano.Store(0) } + +func SetFrameFlowTargetFPS(fps int) { + limit := defaultMaxInFlightFrames + switch { + case fps >= 180: + limit = 8 + case fps >= 120: + limit = 4 + } + if env := strings.TrimSpace(os.Getenv("OVERLORD_DESKTOP_IN_FLIGHT_FRAMES")); env != "" { + if v, err := strconv.Atoi(env); err == nil { + switch { + case v < 1: + limit = 1 + case v > 32: + limit = 32 + default: + limit = int64(v) + } + } + } + maxFrameSlots.Store(limit) +} + +func activeFrameSlotLimit() int64 { + if limit := maxFrameSlots.Load(); limit > 0 { + return limit + } + return defaultMaxInFlightFrames +} diff --git a/Overlord-Client/cmd/agent/handlers/desktop.go b/Overlord-Client/cmd/agent/handlers/desktop.go index 4088072..32a7c70 100644 --- a/Overlord-Client/cmd/agent/handlers/desktop.go +++ b/Overlord-Client/cmd/agent/handlers/desktop.go @@ -33,6 +33,7 @@ func DesktopStart(ctx context.Context, env *rt.Env) error { fps := activeDesktopTargetFPS() interval := time.Second / time.Duration(fps) capture.SetH264TargetFPS(fps) + capture.SetFrameFlowTargetFPS(fps) log.Printf("desktop: starting stream (target fps %d)", fps) ticker := time.NewTicker(interval) defer ticker.Stop() @@ -47,6 +48,7 @@ func DesktopStart(ctx context.Context, env *rt.Env) error { if fps != currentFPS { currentFPS = fps capture.SetH264TargetFPS(fps) + capture.SetFrameFlowTargetFPS(fps) ticker.Reset(time.Second / time.Duration(fps)) log.Printf("desktop: target fps changed to %d", fps) } @@ -73,6 +75,7 @@ func SetDesktopTargetFPS(fps int) int { fps = clampDesktopTargetFPS(fps) desktopTargetFPS.Store(int64(fps)) capture.SetH264TargetFPS(fps) + capture.SetFrameFlowTargetFPS(fps) return fps } diff --git a/Overlord-Server/public/assets/remotedesktop.js b/Overlord-Server/public/assets/remotedesktop.js index bccd1f1..3c3cb06 100644 --- a/Overlord-Server/public/assets/remotedesktop.js +++ b/Overlord-Server/public/assets/remotedesktop.js @@ -788,6 +788,7 @@ import { createKeyboardCapture } from "./keyboard-capture.js"; pushInputToggles(); pushCaptureToggles(); if (qualitySlider) pushQuality(qualitySlider.value); + pushTargetFps(); pushResolution(); } else { setStreamState("idle", "Stopped");