78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
import argparse
|
|
from pathlib import Path
|
|
import sys
|
|
import time
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from localcast.sensor_fusion.spout_output import (
|
|
OpenGLSpoutPointRenderer,
|
|
RenderFrameFileSource,
|
|
SpoutOutputConfig,
|
|
write_status,
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="Publish render-frame packets as a named Spout texture for OBS.")
|
|
parser.add_argument("--frame-json", default=str(ROOT / "calibration" / "runs" / "synthetic-render-frame.json"))
|
|
parser.add_argument("--sender-name", default="LocalCastBridge Point Cloud")
|
|
parser.add_argument("--width", type=int, default=1920)
|
|
parser.add_argument("--height", type=int, default=1080)
|
|
parser.add_argument("--fps", type=float, default=60.0)
|
|
parser.add_argument("--point-scale", type=float, default=1.0)
|
|
parser.add_argument("--demo-if-missing", action="store_true")
|
|
parser.add_argument("--demo-point-count", type=int, default=4096)
|
|
parser.add_argument("--status", default=str(ROOT / "calibration" / "runs" / "stream-spout-status.json"))
|
|
parser.add_argument("--duration", type=float, help="Optional run duration in seconds for smoke tests.")
|
|
args = parser.parse_args()
|
|
|
|
frame_path = Path(args.frame_json)
|
|
status_path = Path(args.status)
|
|
config = SpoutOutputConfig(
|
|
sender_name=args.sender_name,
|
|
width=args.width,
|
|
height=args.height,
|
|
fps=args.fps,
|
|
point_scale=args.point_scale,
|
|
demo_point_count=args.demo_point_count,
|
|
)
|
|
source = RenderFrameFileSource(frame_path, demo_if_missing=args.demo_if_missing, demo_point_count=args.demo_point_count)
|
|
frame_interval = 1.0 / max(1.0, args.fps)
|
|
start = time.monotonic()
|
|
last_status = 0.0
|
|
|
|
with OpenGLSpoutPointRenderer(config) as renderer:
|
|
while True:
|
|
now = time.monotonic()
|
|
if args.duration is not None and now - start >= args.duration:
|
|
break
|
|
frame = source.current_frame(now, config)
|
|
ok = renderer.render(frame)
|
|
if now - last_status >= 1.0:
|
|
write_status(
|
|
status_path,
|
|
sender_name=config.sender_name,
|
|
frames_sent=renderer.frames_sent,
|
|
point_count=len(frame.points),
|
|
frame_path=frame_path,
|
|
last_error=None if ok else "SpoutGL sendTexture returned false",
|
|
)
|
|
last_status = now
|
|
sleep_for = frame_interval - (time.monotonic() - now)
|
|
if sleep_for > 0:
|
|
time.sleep(sleep_for)
|
|
write_status(
|
|
status_path,
|
|
sender_name=config.sender_name,
|
|
frames_sent=renderer.frames_sent,
|
|
point_count=0,
|
|
frame_path=frame_path,
|
|
last_error="stopped",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|