Skip to content

Class ILLIXR::xr_sensor_capture

ClassList > ILLIXR > xr_sensor_capture

ILLIXR plugin that co-captures HEVC-encoded RGB frames, depth frames, and per-sensor matched head poses on the Meta Quest 3.More...

  • #include <plugin.hpp>

Inherits the following classes: ILLIXR::threadloop

Classes

Type Name
struct capture_result
struct latest_head_pose

Public Attributes

Type Name
std::array< capture_result, CAPTURE_RESULT_CACHE_SIZE > capture_result_cache_
std::mutex capture_result_mutex_
size_t capture_result_next_ = 0
int64_t clock_offset_ns_
latest_head_pose latest_head_pose_
std::mutex latest_head_pose_mutex_
double ovr_time_offset_sec_ = 0.0

Public Static Attributes

Type Name
constexpr size_t CAPTURE_RESULT_CACHE_SIZE = 16
IUnityInterfaces * s_unity_interfaces_ = [**nullptr**](namespaceILLIXR.md#function-normalize)
IUnityGraphicsVulkan * s_vk_interface_ = [**nullptr**](namespaceILLIXR.md#function-normalize)

Public Functions

Type Name
void acquire_depth_unity_thread (int64_t predicted_display_time_ns, double ovr_plugin_time_sec, const float * rgb_camera_pose_lh, const float * head_pose_lh, const float * tracking_to_world_lh)
void destroy_vulkan ()
bool init_vulkan ()
void release_depth_after_submit ()
void submit_depth_readback ()
xr_sensor_capture (const std::string & name, phonebook * pb)
~xr_sensor_capture () override

Public Functions inherited from ILLIXR::threadloop

See ILLIXR::threadloop

Type Name
virtual void internal_stop ()
Stops the thread.
virtual void start () override
Starts the thread.
virtual void stop () override
Joins the thread.
threadloop (const std::string & name, phonebook * pb)
~threadloop () override

Public Functions inherited from ILLIXR::plugin

See ILLIXR::plugin

Type Name
std::string get_name () noexcept const
plugin (std::string name, phonebook * pb)
void spd_add_file_sink (const std::string & file_name, const std::string & extension, const std::string & log_level)
auto spdlogger (const char * log_level)
virtual void start ()
A method which Spindle calls when it starts the component.
virtual void stop ()
A method which Spindle calls when it stops the component.
virtual ~plugin () = default

Public Static Functions

Type Name
void set_unity_interfaces (IUnityInterfaces * interfaces)

Protected Types inherited from ILLIXR::threadloop

See ILLIXR::threadloop

Type Name
enum skip_option

Protected Attributes inherited from ILLIXR::threadloop

See ILLIXR::threadloop

Type Name
std::size_t iteration_no = 0
std::size_t skip_no = 0

Protected Attributes inherited from ILLIXR::plugin

See ILLIXR::plugin

Type Name
const std::size_t id_
std::string name_
const phonebook * phonebook_
std::shared_ptr< spdlog::logger > plugin_logger_
const std::shared_ptr< record_logger > record_logger_

Protected Functions

Type Name
virtual void _p_one_iteration () override
Override with the computation the thread does every loop.
virtual skip_option _p_should_skip () override
Gets called in a tight loop, to gate the invocation of _p_one_iteration() __

Protected Functions inherited from ILLIXR::threadloop

See ILLIXR::threadloop

Type Name
virtual void _p_one_iteration () = 0
Override with the computation the thread does every loop.
virtual skip_option _p_should_skip ()
Gets called in a tight loop, to gate the invocation of _p_one_iteration() __
virtual void _p_thread_setup ()
Gets called at setup time, from the new thread.
bool should_terminate ()
Whether the thread has been asked to terminate.

Detailed Description

Acquisition and encoding pipeline

RGB: Camera2 writes directly into MediaCodec's ANativeWindow input surface. The Snapdragon hardware handles NV12 -> HEVC without any CPU copy. The encoder is initialised first so its ANativeWindow can be used as the Camera2 capture target. Completed H.265 output buffers are drained on each threadloop tick.

RGB pose: acquire_depth_unity_thread() samples xrLocateSpace(VIEW,LOCAL) at 90Hz on Unity's main thread (the only valid context for VIEW space) and stores the result in latest_head_pose_ under a mutex. on_capture_completed() snapshots that pose into capture_result_cache_ at the moment of each Camera2 exposure. _p_one_iteration() reads the most recent capture result pose and attaches it to the outgoing frame.

Depth: XR_META_environment_depth OpenXR extension (standard Khronos openxr.h). Unity uses the Vulkan renderer, so depth swapchain images are VkImages. acquire_depth_unity_thread() is called from LateUpdate() via ILLIXRBridge while Unity's XR frame is open. It acquires the depth VkImage and copies it to a host-visible staging buffer via vkCmdCopyImageToBuffer, then maps the buffer to read the R16F pixels to CPU. Vulkan handles are obtained from IUnityGraphicsVulkan via UnityPluginLoad(). Depth format: R16F (float16), 2 bytes/pixel, top-down, inverted NDC. depth_m = near_z / r_value.

Initialisation order

UnityPluginLoad() - captures IUnityGraphicsVulkan (called by Unity at startup) * init_openxr() - reuses Unity's XrInstance/XrSession, loads depth extension * init_vulkan() - creates staging buffer, command pool, fence from Unity's VkDevice * init_encoder() - MediaCodec HEVC, creates input ANativeWindow * init_camera() - Camera2, targeting encoder's ANativeWindow

Configuration (env vars, set via Unity JNI bridge before plugin start)

ILLIXR_CAPTURE_FPS Encoder target FPS hint (default: 2) ILLIXR_ENCODER_BITRATE_BPS HEVC bitrate in bits/s (default: 5000000) ILLIXR_ENCODER_IFRAME_SEC IDR period in seconds (default: 1) ILLIXR_DEPTH_DISABLED Set to 1 to skip depth (default: 0) ILLIXR_MAX_DEPTH_M Far-depth cap in metres (default: 0) ILLIXR_CAMERA_WIDTH Camera capture width (default: 960) ILLIXR_CAMERA_HEIGHT Camera capture height (default: 960)

Publishes: "semantic_frame" (ILLIXR::data_format::semantic_frame)

Public Attributes Documentation

variable capture_result_cache_

std::array<capture_result, CAPTURE_RESULT_CACHE_SIZE> ILLIXR::xr_sensor_capture::capture_result_cache_;

variable capture_result_mutex_

std::mutex ILLIXR::xr_sensor_capture::capture_result_mutex_;

variable capture_result_next_

size_t ILLIXR::xr_sensor_capture::capture_result_next_;

variable clock_offset_ns_

int64_t ILLIXR::xr_sensor_capture::clock_offset_ns_;

variable latest_head_pose_

latest_head_pose ILLIXR::xr_sensor_capture::latest_head_pose_;

variable latest_head_pose_mutex_

std::mutex ILLIXR::xr_sensor_capture::latest_head_pose_mutex_;

variable ovr_time_offset_sec_

double ILLIXR::xr_sensor_capture::ovr_time_offset_sec_;

Public Static Attributes Documentation

variable CAPTURE_RESULT_CACHE_SIZE

constexpr size_t ILLIXR::xr_sensor_capture::CAPTURE_RESULT_CACHE_SIZE;

variable s_unity_interfaces_

IUnityInterfaces * xr_sensor_capture::s_unity_interfaces_;

variable s_vk_interface_

IUnityGraphicsVulkan * xr_sensor_capture::s_vk_interface_;

Public Functions Documentation

function acquire_depth_unity_thread

void ILLIXR::xr_sensor_capture::acquire_depth_unity_thread (
    int64_t predicted_display_time_ns,
    double ovr_plugin_time_sec,
    const  float * rgb_camera_pose_lh,
    const  float * head_pose_lh,
    const  float * tracking_to_world_lh
) 

function destroy_vulkan

void ILLIXR::xr_sensor_capture::destroy_vulkan () 

function init_vulkan

bool ILLIXR::xr_sensor_capture::init_vulkan () 

function release_depth_after_submit

void ILLIXR::xr_sensor_capture::release_depth_after_submit () 

function submit_depth_readback

void ILLIXR::xr_sensor_capture::submit_depth_readback () 

function xr_sensor_capture

ILLIXR::xr_sensor_capture::xr_sensor_capture (
    const std::string & name,
    phonebook * pb
) 

function ~xr_sensor_capture

ILLIXR::xr_sensor_capture::~xr_sensor_capture () override

Public Static Functions Documentation

function set_unity_interfaces

static void ILLIXR::xr_sensor_capture::set_unity_interfaces (
    IUnityInterfaces * interfaces
) 

Protected Functions Documentation

function _p_one_iteration

Override with the computation the thread does every loop.

virtual void ILLIXR::xr_sensor_capture::_p_one_iteration () override

This gets called in rapid succession.

Implements ILLIXR::threadloop::_p_one_iteration


function _p_should_skip

Gets called in a tight loop, to gate the invocation of _p_one_iteration() __

virtual skip_option ILLIXR::xr_sensor_capture::_p_should_skip () override

Implements ILLIXR::threadloop::_p_should_skip



The documentation for this class was generated from the following file /home/friedel/devel/ILLIXR/illixr_release/ILLIXR/plugins/quest3/unity/plugin.hpp