From 094c12c6d84f6b74bd1bad323fcc17d0b6aeee68 Mon Sep 17 00:00:00 2001 From: saphid <4596216+saphid@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:54:05 +1000 Subject: [PATCH] Keep media playing through headset standby Real-Frame testing (2026-09-29) found an unworn headset enters standby within seconds; SetOverlayRaw then returns RequestFailed (23) and the movie died. The player now drops frames during standby, keeps audio and pacing, re-sends stills and the theatre surround after waking, and only errors after five minutes without an accepted frame. A Stop arriving while the player is already shutting down is ignored, so a finished video stays 'ended' instead of 'error: Stopped'. The status now reports the layout's real source (filename/metadata). Docs record the end-to-end device matrix (API, web UI, CLI). Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/img/media-ui-panel.png | Bin 0 -> 59098 bytes docs/vr-video.md | 28 ++++++++++++++++ tests/test_media.py | 55 +++++++++++++++++++++++++++++++ ui/frame_media_player.py | 64 ++++++++++++++++++++++++++++++------ ui/frame_media_remote.py | 2 +- 5 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 docs/img/media-ui-panel.png diff --git a/docs/img/media-ui-panel.png b/docs/img/media-ui-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..2e2a41b85bf752db12d33127020ba5e85ba72ae9 GIT binary patch literal 59098 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 UtqAl3aOa7VoVskev{~SP0f#$^_y7O^ literal 0 HcmV?d00001 diff --git a/docs/vr-video.md b/docs/vr-video.md index 1e242a6..2232915 100644 --- a/docs/vr-video.md +++ b/docs/vr-video.md @@ -75,6 +75,34 @@ All test media were generated by us. No paid content or DRM was involved. ![Our Gaussian-splat stereo preview on the Frame](img/media-splat-proof.png) +**Verified end to end, 2026-09-29** (same build; headset unworn): uploads +through the HTTP API, the web UI and `scripts/push-vr-video.sh`, all played by +the owned player. Our generated test files: + +| Case | Result | +|---|---| +| H.264 half-SBS 1920×1080 with AAC, theatre | 240/240 frames in 8.09 s; audio stream "Frame Control Media" in PulseAudio | +| H.265 half-OU 1920×1080 | 180/180 frames in 6.03 s; red left eye, cyan right | +| H.264 full-SBS 3840×1080, `stereo_mode=left_right` only | Detected from metadata; 150/150 frames in 5.03 s | +| H.264 1280×720, explicit 2D | 150/150 frames in 5.02 s | +| SBS PNG, OU JPEG (theatre) | Correct eye in each capture | +| 3,000-Gaussian `.splat` | Rendered in about 5 s, then held until Stop | +| 2D file on Auto, `_SBS_OU` file, HEIC, VP9 | Refused with the documented message | +| Second Play while one runs | Refused: "Stop the current media…" | + +Stop always left the unit inactive, and no player process remained. + +**Standby (verified):** an unworn Frame turns its displays off a few seconds +after it wakes. `SetOverlayRaw` then returns `RequestFailed` (23). The +first run's movie died there. The player now drops frames while the headset +is in standby, keeps the audio and its clock going, and resumes the picture +when the headset wakes. The 8 s movie above dropped 40 frames and finished. +Stills and the theatre surround are re-sent after waking. Five minutes +without an accepted frame is reported as an error. Headset-view captures +taken during standby show a flat dark frame, not our screen. + +![Media panel in Frame Control while a photo plays on the Frame](img/media-ui-panel.png) + **Verified failed route:** GStreamer 1.24.2's `playbin` selected `v4l2h264dec`, delivered the first RGBA sample and then segfaulted (exit 139) in the basic appsink probe and the OpenVR probe. We do not ship that route. diff --git a/tests/test_media.py b/tests/test_media.py index 9665c27..eb3079f 100644 --- a/tests/test_media.py +++ b/tests/test_media.py @@ -1,6 +1,9 @@ """Owned media planning, eye isolation, decoder choice and fake-Frame ownership.""" +import argparse +import io import json import os +import signal from pathlib import Path import struct import sys @@ -56,6 +59,58 @@ class Media(unittest.TestCase): self.assertNotIn('-re', cmd) self.assertIn('-frames:v', cmd) + def test_video_survives_standby_and_stop_after_end_stays_ended(self): + # Verified 2026-09-29: an unworn Frame enters standby within seconds and + # SetOverlayRaw then returns RequestFailed (23) until it wakes. + calls = [] + + class FakeOverlay: + def __init__(self): + self.closed = False + + def create(self, *a, **k): + return len(calls) + + def call(self, *a): + pass + + def pixels(self, handle, data, w, h): + calls.append((handle, w, h)) + if len(calls) <= 3: + raise player.OverlayBusy('standby') + + def close(self): + # A Stop arriving during cleanup must be ignored, not become an error. + # Call the installed handler directly: a real SIGTERM kills Windows. + handler = signal.getsignal(signal.SIGTERM) + if callable(handler): + handler(signal.SIGTERM, None) + + frame = bytes(4*2*4) + proc = unittest.mock.MagicMock() + proc.stdout = io.BytesIO(frame*4) + proc.wait.return_value = 0 + proc.poll.return_value = 0 + with tempfile.TemporaryDirectory() as d, \ + patch.object(player, 'Overlay', FakeOverlay), \ + patch.object(player, 'probe', return_value=({'codec_name': 'h264', 'width': 4, 'height': 2}, False)), \ + patch.object(player.subprocess, 'Popen', return_value=proc), \ + patch.object(player.time, 'sleep'): + path = Path(d)/'clip_SBS.mp4' + path.write_bytes(b'x') + status = Path(d)/'status.json' + old = signal.getsignal(signal.SIGTERM), signal.getsignal(signal.SIGINT) + try: + player.play(argparse.Namespace(file=str(path), layout='auto', theatre=True, status=str(status))) + finally: + signal.signal(signal.SIGTERM, old[0]) + signal.signal(signal.SIGINT, old[1]) + result = json.loads(status.read_text()) + self.assertEqual((result['state'], result['frames']), ('ended', 4)) + # Surround + first two video frames were dropped; the surround was re-sent after wake. + self.assertEqual(result['dropped'], 3) + self.assertIn((0, 1, 1), calls[3:]) + def test_fake_frame_library_and_traversal(self): with tempfile.TemporaryDirectory() as d, patch.object(remote, 'ROOT', Path(d)): identity = 'a'*32+'/space and quote\'.png' diff --git a/ui/frame_media_player.py b/ui/frame_media_player.py index a6d2bdc..eb9750b 100644 --- a/ui/frame_media_player.py +++ b/ui/frame_media_player.py @@ -33,6 +33,15 @@ SLOTS = { } +class OverlayBusy(RuntimeError): + """SetOverlayRaw's RequestFailed (23): SteamVR isn't taking frames, e.g. the + unworn headset is in standby (verified 2026-09-29). Transient, not fatal.""" + + +# A screen that can't take a frame for this long is broken, not asleep. +BUSY_LIMIT = 300 + + class Overlay: def __init__(self): self.handles = [] @@ -53,6 +62,8 @@ class Overlay: def call(self, name, *values): slot, args = SLOTS[name] rc = C.CFUNCTYPE(C.c_int, *args)(self.table[slot])(*values) + if rc == 23 and name == 'SetOverlayRaw': + raise OverlayBusy('SteamVR is not accepting frames (standby?)') if rc: raise RuntimeError('OpenVR %s failed: %s' % (name, rc)) @@ -135,6 +146,34 @@ def play(args): photo = plan['kind'] == 'photo' command = decoder_command(path, info, width, height, audio, photo) vr, proc, frames, started = None, None, 0, time.monotonic() + dropped, busy_since, pending = 0, None, [] + + def show(handle, data, w, h): + """Submit a frame; during standby drop it (video) or report False (stills retry).""" + nonlocal dropped, busy_since + try: + vr.pixels(handle, data, w, h) + except OverlayBusy: + dropped += 1 + busy_since = busy_since or time.monotonic() + if time.monotonic() - busy_since > BUSY_LIMIT: + raise RuntimeError('SteamVR stopped accepting frames for %d s' % BUSY_LIMIT) + return False + busy_since = None + while pending: # e.g. the theatre surround, if it was sent during standby + item = pending.pop(0) + if not show(*item): + pending.insert(0, item) + break + return True + + def hold(handle, data, w, h): + """Keep a still (photo or splat) up until Stop, retrying through standby.""" + shown = False + while True: + shown = shown or show(handle, data, w, h) + time.sleep(1) + # systemd sends SIGTERM to the whole unit, including ffmpeg. Python unwinds # ownership; no unrelated Steam/SteamVR process or setting is touched. def stop(signum, frame): @@ -146,14 +185,13 @@ def play(args): if args.theatre: surround = vr.create('framecontrol.media.surround', 40, 4, order=0) vr.call('SetOverlayAlpha', surround, .85) - vr.pixels(surround, b'\x00\x00\x00\xff', 1, 1) + if not show(surround, b'\x00\x00\x00\xff', 1, 1): + pending.append((surround, b'\x00\x00\x00\xff', 1, 1)) screen = vr.create('framecontrol.media.screen', 3 if args.theatre else 1.6, 2, plan['layout'] != 'mono', aspect) if splat: - vr.pixels(screen, data, width, height) write_status(status, state='playing', file=path.name, frames=1, **plan) - while True: - time.sleep(1) + hold(screen, data, width, height) proc = subprocess.Popen(command, stdout=subprocess.PIPE) video_start = time.monotonic() while True: @@ -163,11 +201,14 @@ def play(args): data, outw, outh = frame_media.stereo_pixels(data, width, height, plan['layout']) if not photo: time.sleep(max(0, video_start + frames/30 - time.monotonic())) - vr.pixels(screen, data, outw, outh) + if photo: + still = data, outw, outh + else: + show(screen, data, outw, outh) frames += 1 if frames == 1 or frames % 30 == 0: write_status(status, state='playing', file=path.name, frames=frames, - seconds=time.monotonic()-started, **plan) + dropped=dropped, seconds=time.monotonic()-started, **plan) if not photo: time.sleep(max(0, video_start + frames/30 - time.monotonic())) rc = proc.wait(timeout=10) @@ -176,12 +217,15 @@ def play(args): if not frames: raise RuntimeError('Decoder produced no frames') if photo: - while True: - time.sleep(1) - write_status(status, state='ended', frames=frames, seconds=time.monotonic()-started) + hold(screen, *still) + write_status(status, state='ended', frames=frames, dropped=dropped, + seconds=time.monotonic()-started) except InterruptedError: - write_status(status, state='stopped', frames=frames) + write_status(status, state='stopped', frames=frames, dropped=dropped) finally: + # A Stop that lands during cleanup must not turn 'ended' into an error. + signal.signal(signal.SIGTERM, signal.SIG_IGN) + signal.signal(signal.SIGINT, signal.SIG_IGN) if proc: if proc.poll() is None: proc.terminate() diff --git a/ui/frame_media_remote.py b/ui/frame_media_remote.py index 3b70bfe..fc0b2ae 100644 --- a/ui/frame_media_remote.py +++ b/ui/frame_media_remote.py @@ -88,7 +88,7 @@ def run(body): '--property=StandardOutput=append:'+str(RUNTIME/'player.log'), '--property=StandardError=append:'+str(RUNTIME/'player.log'), 'python3', str(RUNTIME/'frame_media_player.py'), str(path), - '--layout', plan['layout'], '--status', str(STATUS)] + '--layout', body.get('layout', 'auto'), '--status', str(STATUS)] if body.get('theatre'): command.append('--theatre') started = subprocess.run(command, capture_output=True, text=True, timeout=15)