#!/usr/bin/env python3 """ft-eyes-replay: play a recording into the shared-frame layout, as ft-eyegrab --share would, at the recorded pace, to test ft-eyes without the headset. Usage: lab/py lab/ft-eyes-replay NAME [PATH] [--from S] [--for S] NAME is a recording (a bare name is in eyes_lab.CAPTURES). PATH defaults to /dev/shm/frametop-eyes-cams-replay; run ft-eyes with FT_EYES_CAMS=PATH (and FT_EYES_GAZE=... so it doesn't overwrite the live output). """ import mmap import os import struct import sys import time from pathlib import Path import numpy as np sys.path.insert(0, str(Path(__file__).resolve().parent)) from eyes_lab import capture # noqa: E402 W, H, SLOTS = 512, 400, 8 ESIZE = 64 + W * H def main(argv): cap = capture(argv[0]) path = argv[1] if len(argv) > 1 and not argv[1].startswith("--") else "/dev/shm/frametop-eyes-cams-replay" start = float(argv[argv.index("--from") + 1]) if "--from" in argv else 0.0 length = float(argv[argv.index("--for") + 1]) if "--for" in argv else 1e9 idx = np.array([[float(v) for v in l.split()] for l in (cap / "index.txt").read_text().splitlines() if len(l.split()) == 4]) frames = np.memmap(cap / "frames.raw", dtype=np.uint8, mode="r").reshape(-1, H, W) size = 64 + 2 * SLOTS * ESIZE if os.path.exists(path): os.unlink(path) fd = os.open(path, os.O_RDWR | os.O_CREAT | os.O_EXCL, 0o600) os.ftruncate(fd, size) mm = mmap.mmap(fd, size) os.close(fd) struct.pack_into("<6I2QI", mm, 0, 0x31434546, 1, W, H, SLOTS, ESIZE, 0, 0, os.getpid()) count = [0, 0] t0 = idx[0, 3] + start wall0 = time.monotonic() try: for i in range(len(frames)): t = idx[i, 3] if t < t0: continue if t - t0 > length: break delay = (t - t0) - (time.monotonic() - wall0) if delay > 0: time.sleep(delay) cam = int(idx[i, 2]) n = count[cam] off = 64 + (cam * SLOTS + n % SLOTS) * ESIZE seq = struct.unpack_from("