Data produced by the OpenXR module
This module parses and republishes the SimulationFrame the HEAT OpenXR API layer pushes,
unmodified - it does not rebuild the frame, and does not generate its own entity id.
Entity
The layer emits a single fixed entity per frame: id 0x4F505852 (the ASCII bytes “OPXR” packed
into a uint64), name OpenXR_Data. This module does not override either.
Pose and hands
Carried on SpatialComponent: pose (head),
left_controller_pose, right_controller_pose, left_hand and right_hand. The layer’s video
path does not do CPU pixel readback any more (see below), so left_image/right_image on this
component are not populated by this pipeline.
Video
Carried on StreamComponent, as up to two
VideoSource entries (one per eye, named eye.left/eye.right) inside sources, each with
codec set to "H264" and video_data holding one encoded access unit’s raw bytes. Per the HEAT
OpenXR API layer’s own design documentation (CaptureApp-OpenXR, docs/superpowers/specs/):
| Parameter | Value |
|---|---|
| Codec | H264, one independent stream per eye |
| Max encode dimension | 1088px (16-pixel aligned) |
| Bitrate | ~8 Mbps per eye, constant bitrate |
| GOP size | 90 submitted frames |
| Submission cadence | Native XR tick rate (typically 90Hz), divided by a layer-side throttle that may submit less than every tick |
Both eyes’ access units for the same tick are correlated and sent together in one frame when possible; if one eye’s access unit is delayed beyond a bounded wait, the layer sends whatever it has for that tick rather than holding the healthy eye’s video indefinitely. A tick can therefore legitimately carry only one eye’s video, not two - this module does not treat that as an error.
What this module does not do
It does not decode H264, does not inspect frame content, and does not verify that pose, hand or
video data is internally consistent - it validates only that the pipe payload parses as a
SimulationFrame (see Troubleshooting).