Files
StarPilot/openpilot/starpilot/galaxy/camera_snapshot_worker.py
T
Prabhaav Pillai c532223fa0 Restore V-Adj Spot Monitoring warnings and polish Galaxy settings, cameras, and updates
Bundle the verified VASM model, enable it at startup, and split VASM and vision speed-sign inference across little cores when both are active.
Restore VASM warnings in PiP activation, red outlines, and onroad blind-spot borders, including expanded Android Auto views.
Improve cabin snapshots with longer warm-up, adjusted capture timeouts, a fresh preview frame, and clearer capture buttons and save prompts.
Polish Galaxy settings with dimmed gated controls and icons, clearer vehicle fingerprinting and steering availability descriptions, rounded speed-offset ranges, and immediate refresh after saving.
Improve updater startup messages and preserve update/reconnect screens across service interruptions and restarts.
Add regression tests for the updated behavior.
2026-10-19 23:07:19 -04:00

66 lines
2.3 KiB
Python

"""CPU-only frame reader. Does not start or stop camerad or change Params."""
from io import BytesIO
import sys
import time
from PIL import Image
from msgq.visionipc import VisionIpcClient
from openpilot.cereal.visionipc import VisionStreamType
from openpilot.starpilot.galaxy.camera_snapshot import MAX_JPEG_BYTES
from openpilot.system.camerad.snapshot import extract_image
STREAMS = {"cabin": VisionStreamType.VISION_STREAM_CABIN, "wide": VisionStreamType.VISION_STREAM_WIDE_ROAD,
"narrow": VisionStreamType.VISION_STREAM_NARROW_ROAD}
CABIN_SETTLE_NS = 10_000_000_000
def boot_ns():
return time.clock_gettime_ns(getattr(time, "CLOCK_BOOTTIME", time.CLOCK_MONOTONIC))
def capture(camera, *, client_factory=VisionIpcClient, clock=boot_ns):
started = clock()
client = client_factory("camerad", STREAMS[camera], True)
while not client.connect(False):
if clock() - started > 9_000_000_000:
return None
time.sleep(.1)
connected = clock()
while clock() - started < (22_000_000_000 if camera == "cabin" else 10_000_000_000):
frame = client.recv(timeout_ms=100)
now = clock()
if camera == "cabin" and now - connected < CABIN_SETTLE_NS:
continue
# Native camerad does not populate VIPC extra.valid; use capture freshness.
if frame is None or not started < client.timestamp_sof <= client.timestamp_eof <= now:
continue
if now - client.timestamp_sof > 500_000_000:
continue
width, height, stride, uv_offset = frame.width, frame.height, frame.stride, frame.uv_offset
uv_height = ((height // 2 + 15) // 16) * 16
if (not 0 < width <= 4096 or not 0 < height <= 4096 or width % 2 or height % 2 or
not width <= stride <= 8192 or stride % 2 or not stride * height <= uv_offset <= stride * 4096 or
uv_offset % stride or len(frame.data) < uv_offset + stride * uv_height):
return None
image = Image.fromarray(extract_image(frame))
image.thumbnail((1280, 720))
output = BytesIO()
image.save(output, format="JPEG", quality=85)
body = output.getvalue()
return body if len(body) <= MAX_JPEG_BYTES else None
return None
if __name__ == '__main__':
try:
result = capture(sys.argv[1]) if len(sys.argv) == 2 and sys.argv[1] in STREAMS else None
if result is not None:
sys.stdout.buffer.write(result)
else:
sys.exit(1)
except Exception:
sys.exit(1)