mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 00:00:21 +02:00
- Per-frame timing on the Mac's clock (capture, encode, network, decode, draw), viewer clock sync and reports, input echo, /stats and a HUD. - scripts/macview-bench.py: repeatable runs on the real Frame, a shaping relay (no sudo), interleaved A/B between agent settings; results in bench/results/. - Adaptive controller: ack-based send gate with jitter-aware slack, AIMD bitrate that knows when a stream is app-limited, fps then size tiers. On a 50->3->50 Mbit/s step, scroll p95 went from 4.7 s to 72 ms; no cost on a clean link. - Separate mode: real AppKit event loop (HiDPI and NSScreen now work), cropped capture for fixed-size windows, windows kept on their display, graceful quit restores windows; stop/start races fixed. - Encoder timeline clamp (no oversized frame after a pause). - Frame Control shows each live stream's fps, delay, bitrate and tier. Reviewed by GPT-6 Astra xhigh (read-only), 7 rounds; findings fixed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
25 lines
1.3 KiB
HTML
25 lines
1.3 KiB
HTML
<!doctype html>
|
|
<!-- Control experiment, run on the Frame itself: how often does Chromium on
|
|
gamescope put a canvas animation on screen, with no network or decoding
|
|
involved? Draws every animation frame for ?s= seconds and writes the
|
|
frame-gap histogram per second into the title, where xprop can read it. -->
|
|
<html><head><meta charset="utf-8"><title>fmv-present</title></head>
|
|
<body style="margin:0;background:#000"><canvas id="c" width="1280" height="720" style="width:100%;height:100%"></canvas>
|
|
<script>
|
|
const q = new URLSearchParams(location.search), secs = +q.get("s") || 15, tag = q.get("tag") || "";
|
|
const ctx = document.getElementById("c").getContext("2d", { alpha: false, desynchronized: true });
|
|
const perSec = []; let t0 = 0, last = 0, n = 0, gaps = [];
|
|
function frame(t) {
|
|
if (!t0) t0 = last = t;
|
|
ctx.fillStyle = "#123"; ctx.fillRect(0, 0, 1280, 720);
|
|
ctx.fillStyle = "#fff"; ctx.fillRect((n * 21) % 1280, 0, 20, 720); n++;
|
|
const s = Math.floor((t - t0) / 1000);
|
|
(perSec[s] = perSec[s] || []).push(t - last); last = t;
|
|
if (t - t0 < secs * 1000) return requestAnimationFrame(frame);
|
|
const out = perSec.map(g => g.length).join(",");
|
|
document.title = `[${tag}] done fps/s=${out}`;
|
|
}
|
|
document.title = `[${tag}] running`;
|
|
requestAnimationFrame(frame);
|
|
</script></body></html>
|