Two knobs for the 60 fps attempt, both measured on Bad Apple:
clip_from_video.py --block N averages each NxN block, thresholds the average and
draws the block flat. The point is destination words: at 60 fps the clip changes
80 tiles/frame unstylised, 54 at 8x8 and 29 at 16x16, against the ~44-tile budget
that MAME's ~3.4 us/word allows in 16.7 ms. A side effect worth knowing: with
16-pixel blocks every 32x32 tile is one of exactly 2^4 combinations, so the 256
entry dictionary represents the stylised clip with zero error (measured: 16
entries used, "reconstruction 0 bit(s)", PSNR inf, mean delta 141 B against 496 B
for the unstylised clip).
vidsend.py --keyframe-every N exposes the cadence that TileSender already had as
a constructor argument. A keyframe repaints all 1,280 tiles (~264 ms of MAME CPU
at the measured 0.22 ms/tile), so the default 60-frame cadence costs ~4.4 ms on
average per frame at 60 fps -- a tenth of the budget spent on repairs. The
13,167-frame stylised clip ships 220 keyframes at the default; 600 measured 6 in
the same window.
Measured on the stylised 60 fps cache (13,167 frames, 16 dictionary entries):
--fps 60, default cadence 643 of 805 accepted (80%), drops=8
--fps 45 484 of 520 accepted, drops=0, sender PASS
--fps 60, --keyframe-every 600 451 of 519 accepted, drops=5
So the stylised clip roughly doubles acceptance against the same 60 fps send
(40% -> 80%) but MAME still caps the clean rate around 36-45 fps.