CloudXR server not working on HP men laptop (4070 laptop GPU)

Goodmorning,

I have followed all the steps of this unofficial debbuging guide:

Unofficial Debug Guides 1: Does my CloudXR server even work? - XR – VR/AR/MR / CloudXR (VR and AR Streaming) - NVIDIA Developer Forums

At the end of it Im unable to run the steam vr mountains section (the previous pirate ship demo is working)

Im attaching the logs for your refrence:

  1. SteamVR:
    CloudXR Server - SteamVR Log 2024-10-22 11.24.13.txt (2.5 KB)
    Streamer Server Log 2024-10-22 11.24.18.txt (12.5 KB)

  2. CloudXR:
    CloudXR Client Log 2024-10-22 11.25.34.txt (747 Bytes)

Any help would be appreciated! Thanks

Your logs indicate two things:

  1. The server started successfully but a client never (seemed to) try to connect.
  2. The client log ends long before it even attempts to connect.

A couple of random things to check on:

  • Do you have a tethered HMD connected (VIVE Pro, Valve Index, etc.)? If so, disconnect and restart SteamVR. You can’t stream SteamVR from a computer with an attached HMD.
  • Do you have the Oculus for PC or other (non-SteamVR) XR software installed? If so, close Oculus/Quest software, go into Task Manager and kill all Oculus/Quest related processes, restart SteamVR and try again. Oculus for PC “injects” itself into SteamVR, blocking CloudXR (and some other HMDs).
  • Check that nothing is running on the integrated graphics. I cannot help you with details on how, but that’s sometimes an issue with laptops.
  • Generally, review the cautions/warnings at the top of the debug guide.

And if you do figure anything out, please let us know! There are others stuck here as well.

1 Like

Thanks for this. I will test and get back to you

Need your help in one more thing. For checking if we can stream from SteamVR, do I have to run SteamVR on a different “client” machine or can I run it on the server itself? Im talking about this step: Unofficial Debug Guides 1: Does my CloudXR server even work?

I have linked the exact step of the guide in the above url.

Also, you mentioned that hmd should not be connected to SteamVR, but unless I do that SteamVR gives error : “Headset not detected, please make sure headset is connected properly, then reset it below”.

And I also get this error window:

Please help

Edited to put the critical piece first:
There is a critical typo in the command line for running the client in that step. The critical missing flag is -w, so that the complete correct command is:

.\CloudXRClientSample.exe -s 127.0.0.1 -w

Full answer follows:

On the server, the CloudXR SteamVR Server Driver is the HMD connected to SteamVR, but you will get the “no HMD detected” message until a client connects. This is because SteamVR needs to know everything about the HMD as soon as it connects, but CloudXR cannot know exactly what HMD will be connected until a client connects and tells it what kind of HMD there is on the client side.

Yes, you can and should do this step on a single computer. The architecture of this configuration is roughly this:

SteamVR "mountains" "app"
  <> SteamVR runtime
    <> CloudXR Server Runtime (virtual HMD)
      <> "network" (loopback interface: 127.0.0.1)
    <> CloudXR client library
  <> CloudXR sample application
<> "Fake" HMD running on the desktop

Note importantly that SteamVR is only involved, in this scenario, on the server side of the network. SteamVR is a global singleton: you cannot run more than one copy on a single computer, and it can only server a single HMD. So for CloudXR, it can either be attached to the client or the server or (in the case of some of SampleServer/Client situations) neither. It can never be connected to both the client and the server.

If you want to stream to a SteamVR HMD from the standard SteamVR server, then, no, you cannot use just one computer. You have to have two different copies of SteamVR, one connected to the client, one connected to the server.

However.

I now see that there is a critical typo in the command line for running the client in that step. The critical missing flag is -w, so that the complete correct command is:

.\CloudXRClientSample.exe -s 127.0.0.1 -w

This missing “-w” flag is what’s causing your issue. This flag is what makes the client use the “windowed” mode, instead of trying to be an OpenVR/SteamVR client (the default). Therefore, the client is trying to connect to SteamVR as an application, to get the HMD properties on the client side to send on the the server…but the server is waiting on the client to send it HMD properties before it connects to SteamVR as an HMD!

I’m correcting the original post now, sorry about the confusion!

1 Like

Thanks for that typo fix, It definitely helped me get that step working.
Just found one weird behaviour. My client window automatically stops closes after some time Attaching the logs here:

CloudXR Client Log 2024-11-07 14.50.17.txt (5.7 KB)
Streamer Client Log 2024-11-07 14.50.17.txt (233.1 KB)

And this is what I was getting on the terminal

Is this the expected behaviour?

Also, Im now at the next step: " Check: Can you stream your XR application?".
I am supposed to launch my XR application but im afraid I dont have any. Should I build an XR application in Unity? or in any of the Omniverse apps like OpenUSD? Please guide me here as well.

Nothing seems wrong in the client. But SteamVR is typically set up to “sleep” the headset after a period of inactivity, which causes the server to stop sending frames. While connected, check you SteamVR settings.

As for an application to test: If you don’t have one of your own, building one with Unity (targeting Windows/OpenXR) would certainly be one option, but testing various free XR applications like Valve’s The Lab or Google Earth VR would be another way.

Thanks for the info. So currently I am trying to establish a connection between VR server and a client, I followed the following steps.

  1. Open the USD composer in Omniverse launcher, create one scene, add some 3-D object, then in the start VR panel window select cloudXR this has to be done in the laptop, which has RTX graphics card and cloud XR installed and click on start VR.
  2. Run the command line of cloud client sample.EXE with IP address of the local server in same laptop.

After running this, I am getting the error : The handshake with the server failed [cxrError_Server_Handshake_Failed].

I also doubt that ports(TCP,UDP) mentioned in the USD Composer to be open for the server is enabled or not!
Is there anyway I can open the ports in USD composer application?

I have attached the logs for above.

Streamer Client Log 2024-11-15 12.39.01.txt (5.6 KB)

CloudXR streaming with Omniverse is a bit delicate.

Assuming you’re trying to do this:

Omniverse > SteamVR > CloudXR server plugin > CloudXR client

Then in Omniverse, make sure you are selecting the SteamVR plugin, not the CloudXR plugin. If that’s not the problem, then we’ll need to see some server logs to make further progress.

Also, before you do this, I would shut down everything and either manually clean up SteamVR, CloudXR and OV processes in Task Manager, or (more simply) reboot the computer.

Thanks for the guidance so far, I am able to successfully complete step 3 of the unofficial guide (Can you Stream your XR app?)

Currently we are in the process of setting up the network infrastructure for step 4 (last step). In the meanwhile Im trying to stream the omniverse usd composer app to my meta quest. I have the unity app running on my headset. This app has the cloud xr client unity package with the IP address of the server (I have cross checked this)

The steps im doing are as follows:

  1. Run steamvr app
  2. in my Usd launcher scene → VR → SteamVr → Start VR
  • Now im able to see “CXR” on SteamVR window
  1. Start the app on my headset

Im expecting my omniverse usd scene to be streamed on my headset, but its not working. My unity scene is showing on my headset, that is all.

Can you please guide me on how to setup the Unity project to enable cloud xr on our server ip address. Do we need to change the NVIDIA scripts inside the unity package?

I am attaching the CloudXRManager.cs code that comes with your Unity plugin. In the very beginning there is a commented area that talks about how to set it up in unity. Please guide me through it.

/*
* Copyright (c) 2022-2023, NVIDIA CORPORATION.  All rights reserved.
*
* NVIDIA CORPORATION, its affiliates and licensors retain all intellectual property
* and proprietary rights in and to this material, related documentation
* and any modifications thereto.  Any use, reproduction, disclosure or
* distribution of this material and related documentation without an express
* license agreement from NVIDIA CORPORATION or its affiliates is strictly prohibited.
*/

using System.IO;
using System.Collections.Generic;

using UnityEngine;
using UnityEngine.XR;

// Included for access to CloudXRCommon.h etc. enums
using CloudXrClientWrapper;


namespace CloudXR {

    // Just before the tracked pose driver, if enabled.
    [DefaultExecutionOrder(-30001)]
    [AddComponentMenu("NVIDIA/CloudXR Manager")]
    //[Serializable]
    [RequireComponent(typeof(AudioListener))]    
    public class CloudXRManager : MonoBehaviour {
        /*
        This class is the primary interface into the CloudXR Client for Unity plugin.

        Lifecycle:
          0. Add to project
             a. Add this script to the main camera (typically under XRRig or similar)
             b. Retrieve this script in your own script by:
                CloudXRManager cxrManager = Camera.main.GetComponent<CloudXRManager>();
          1. Configure
             a. config: use LoadConfigFromFile=True to use defaults or load from file, or set up manually:
                    cxrManager.config = new CxruConfig();
                    cxrManager.config = GetDefaultConfig();
                    // Then set up individual settings
          2. Register for events
             a. implement callback c_OnStatusChanged(object sender, StatusEventArgs e)
             b. cxrManager.statusChanged += OnCxrStatusChange;
          3. Connect to a server
             a. Set server_ip:
                    cxrManager.server_ip = serverAddress; // IP string like "127.0.0.1"
             b. cxrManager.Connect();
                    note that this will fire a "configuring" event
          4. Handle the CloudXRManager.S state changes in c_OnStatusChanged(sender,e):
             e.state == 
                S.connecting: actively trying to set up a connectiong, no frames streaming, lobby visuals
                S.running: streaming has started, transition to streaming visuals
                S.disconnecting, S.error, S.dormant: streaming has stopped or failed, or is not requested; lobby visuals
                S.error: check e.result for more information
        */


        // ============================================================================
        // Configuration

        // The primary configuration; publicly settable; set up before calling Connect()
        private CxruConfig _config;
        public CxruConfig config { 
            get {return _config;}
            set {_config=value;}
        }

        private string _server_ip;
        public string server_ip {
            get {return _config.serverAddress;}
            // CXRUNITY-223
            set {_config.serverAddress=value;}
        }

        public static CxruConfig GetDefaultConfig() {
            // Initialize with non-default defaults.
            // bool defaults to false; int/uint/float to 0.
            CxruConfig newConfig = new CxruConfig();
            newConfig.cxrLibraryConfig.cxrRecieverConfig.logMaxSizeKB = -1;
            newConfig.cxrLibraryConfig.cxrRecieverConfig.logMaxAgeDays = -1;

            // config.cxrLibraryConfig.cxrDebugConfig.enableAImageReaderDecoder = true;
            newConfig.cxrLibraryConfig.cxrDebugConfig.outputLinearRGBColor = false;

            newConfig.cxrLibraryConfig.cxrDeviceConfig.receiveAudio = true;
            newConfig.cxrLibraryConfig.cxrDeviceConfig.sendAudio = false;
            newConfig.cxrLibraryConfig.cxrDeviceConfig.maxResFactor = 1f;
            newConfig.cxrLibraryConfig.cxrDeviceConfig.foveatedScaleFactor = 50;
            newConfig.cxrLibraryConfig.cxrDeviceConfig.maxClientQueueSize = 0f; // Arjun said on call 2022-08-02 that this is correct to invoke the default
            newConfig.cxrLibraryConfig.cxrDeviceConfig.angularVelocityInDeviceSpace = true;
            newConfig.cxrLibraryConfig.cxrDeviceConfig.maxVideoBitrateKbps = 0; // Use library default

            newConfig.cxrLibraryConfig.cxrConnectionConfig.clientNetwork = cxrNetworkInterface.cxrNetworkInterface_WiFi5Ghz;
            newConfig.cxrLibraryConfig.cxrConnectionConfig.topology = cxrNetworkTopology.cxrNetworkTopology_LAN;

            newConfig.debugLevel = DebugLevel.Info;
            newConfig.doLDAT = true;

            newConfig.serverAddress = "0.0.0.0";//comments: take from ip field
            return newConfig;
        }


        public bool LoadConfigFromFile = true;
        public string ConfigFileName = "cxrUnityConfig.json";

        private CxruConfig LoadConfig() {
            // This is a reasonable default 
            CxruConfig newConfig;
            string fname = $"{Application.persistentDataPath}/{ConfigFileName}";
            if (File.Exists(fname)) 
            {
                string jsondata = File.ReadAllText(fname);
                newConfig = JsonUtility.FromJson<CxruConfig>(jsondata);
            }
            else 
            {
                newConfig = GetDefaultConfig();
            }
            string jsonString = JsonUtility.ToJson(newConfig,true);
            string outName = $"{Application.persistentDataPath}/used_{ConfigFileName}";
            Log.V("json config");
            Log.V(jsonString);
            File.WriteAllText(outName, jsonString);
            return newConfig;
        }


        // ============================================================================
        // Startup
        CxrUnityXRManager m_unityXrManager = null;
        void Start() {
            m_unityXrManager = new CxrUnityXRManager();
        }

        // ============================================================================
        // Interfaces during streaming

        private StereoPosedFrame _latestValidFrame = null; 
        public StereoPosedFrame latestValidFrame {
            get {return _latestValidFrame;}
        }

        public void SignalLatency(bool state) {
            client?.SignalLatency(state);
        }


        // ============================================================================
        // Input bindings

        private CxruDeviceBinding[] m_bindings = null;
        public void SetBindings(CxruDeviceBinding[] bindings) {
            m_bindings = bindings;
        }


        // ============================================================================
        // State machine public interfaces

        public enum S {
            dormant, configuring, connecting, running, disconnecting, disconnected,
            error
        }

        // Subscribe to this event to get updates whenever the state machine status changes
        public event System.EventHandler<StatusChangeArgs> statusChanged;

        public class StatusChangeArgs : System.EventArgs
        {
            public S previous_status, new_status;
            public CxruResult result;
        }

        public bool Disconnect() {
            doStatusChange(S.disconnecting,null);
            return true;
        }

        public bool Connect() {
            if (m_bindings == null) {
                Log.E("Tried to call Connect before setting up bindings.");
                return false;
            }
            if ( (state == S.dormant) || (state == S.disconnected) ) {
                doStatusChange(S.configuring,null);
                return true;
            } else {
                doStatusChange(S.error,null);
                return false;
            }
        }

        // ============================================================================
        // State machine internal code

        private S state = S.dormant;
        public S currentState {
            get {return state;}
        }

        protected void doStatusChange(S new_status, CxruResult result) {
            state = new_status;

            if (new_status == S.error) {
                client.Disconnect();
                Teardown();
            }

            StatusChangeArgs args = new StatusChangeArgs();
            args.previous_status = state;
            args.new_status = state;
            args.result = result;
            System.EventHandler<StatusChangeArgs> handler = statusChanged;
            if (handler != null) {
                handler(this,args);
            }
        }


        private CxruResult DoState_Configuring() {
            if (state != S.configuring) Log.E($"Call to DoState_Configuring in other state: {state}");
            if (m_bindings == null) Log.E($"Should not be possible to get to 'configuring' with null bindings");
            client = new CloudXRClient(config ,m_unityXrManager, m_bindings);
            Log.I("CloudXR Client library version: " + client.Version());
            CloudXRConnection cxrConn;
            CxruResult result = client.CreateReceiver(out cxrConn);            
            if (result.succeeded) {
                Log.I("Finished creating reciever!");
            } else {
                if (Time.frameCount%100==0) Log.I($"Not quite done; message {result.message}");
            }
            return result;
        }
        private CxruResult DoState_Connecting() {
            if (state != S.configuring) Log.E($"Call to DoState_Connecting in other state: {state}");
            CxruResult result = client.StartConnect(server_ip);
            Log.D($"Attempted to start connection, result: {result.succeeded}, {result.api_cxrErrorString}");
            return result;
        }
        private uint framesLatched = 0;
        private CxruResult DoState_Running() {
            client.FireControllerEvents();

            StereoPosedFrame frame = null;
            uint timeoutMs = 5;
            CxruResult result = client.LatchFrame(out frame, timeoutMs);
            if (result.succeeded) {
                framesLatched += 1;
                if (framesLatched==1) {
                    Log.D("First frame latched, texture copied!");
                } else if (framesLatched % 1000 == 0) {
                    Log.D($"Latched {framesLatched} frames");
                }
                _latestValidFrame = frame;
            } else {
                Log.I("LatchFrame did not succeed, msg:" + result.message + "\n" + "    " + result.api_cxrErrorString);
            }

            // This condition is a hack meaning "wait until we are so connected that
            // frames are consistently flowing"
            if (framesLatched % 12 == 6) {
                result = client.UpdateControllers();
                if (result.succeeded) { 
                    // Log.I("Controller add/remove update");
                }
                else {
                    Log.W($"Failed controller update! {result.api_cxrError}, '{result.message}' ");
                }
            }

            return result;
        }
        private CxruResult DoState_Disconnecting() {
            _latestValidFrame = null;
            CxruResult result = client.Disconnect();
            Teardown();
            if (result.succeeded) {
            }
            else {
                Log.W("Disconnect() did not succeed, msg:" + result.message + "\n" + "    " + result.api_cxrErrorString);
            }
            return result;
        }

        private void Teardown() {
            client = null;
            quittingThreads = true;
            if (poseUpdateThread!=null) {
                poseUpdateThread.Join();
            }
        }

        /// <inheritdoc />
        protected virtual void Update()
        {
            if (!enabled)
                return;
            CxruResult result;
            switch(state) {
                case S.dormant:
                    return;
                case S.configuring:
                    result = DoState_Configuring();
                    if (result.succeeded) {
                        result = DoState_Connecting();
                        if (result.succeeded) {
                            doStatusChange(S.connecting,null);
                        }
                        else {
                            doStatusChange(S.error,result);
                            Log.E($"Error while initiating connection! {result.message}");
                        }
                    }
                    break;
                case S.connecting:
                    switch (client.m_status) {
                        case CloudXRStatus.connecting:
                            return;
                        case CloudXRStatus.connected:
                            doStatusChange(S.running,null);
                            if (poseUpdateThread==null) {
                                poseUpdateThread = new System.Threading.Thread(new System.Threading.ThreadStart(PoseSendThread));
                            }
                            quittingThreads = false;
                            poseUpdateThread.Start();
                            Log.I("Connected!");  
                            break;
                        case CloudXRStatus.error:
                        case CloudXRStatus.connectionFailed:
                            doStatusChange(S.error,client.lastCallbackResult);
                            string reason = client.lastCallbackResult.api_cxrErrorString;
                            uint code = (uint)client.lastCallbackResult.api_cxrError;
                            Log.E($"Unhandled error connecting: code {code}, '{reason}'"); 
                            break;
                        case CloudXRStatus.disconnected:
                        case CloudXRStatus.offline:
                            result = new CxruResult();
                            result.message = $"CloudXR client: invalid state {state} while connecting";
                            doStatusChange(S.error,result);
                            Log.E(result.message); 
                            break;
                    } 
                    break;
                case S.running:
                    if (!poseUpdateThread.IsAlive) {
                        doStatusChange(S.error,new CxruResult{succeeded=false,message="Pose thread quit early"});
                        Log.E("Pose thread quit early!!");
                        break;
                    }
                    switch (client.m_status) {
                        case CloudXRStatus.connected:
                            result = DoState_Running();
                            break;
                        case CloudXRStatus.error:
                            doStatusChange(S.error,client.lastCallbackResult);
                            string reason = client.lastCallbackResult.api_cxrErrorString;
                            uint code = (uint)client.lastCallbackResult.api_cxrError;
                            Log.E($"Unhandled error while streaming: code {code}, '{reason}'"); 
                            break;
                        case CloudXRStatus.disconnected:
                        case CloudXRStatus.connectionFailed:
                        case CloudXRStatus.offline:
                            result = new CxruResult();
                            result.message = $"CloudXR client: invalid state {client.m_status} while streaming";
                            doStatusChange(S.error,result);
                            Log.E(result.message); 
                            break;
                    }
                    break;
                case S.disconnecting:
                    switch (client.m_status) {
                        case CloudXRStatus.connected:
                        case CloudXRStatus.offline:
                        case CloudXRStatus.error:
                        case CloudXRStatus.connectionFailed:
                        case CloudXRStatus.disconnected:
                            result = DoState_Disconnecting();
                            if (result.succeeded)
                                doStatusChange(S.dormant,result);
                            else {
                                doStatusChange(S.error,result);
                            }
                            break;
                    }
                    break;
                case S.disconnected:
                    break;
            }

        }


        // ============================================================================
        //  MonoBehaviour life cycle

        private CloudXRClient client;
        // private AudioClip m_streamingAudioClip;
        // private AudioSource m_streamingAudioSource;

        /// <inheritdoc />
        protected virtual void OnEnable()//onBtnclick()
        {
            _SetupAudio();
            if (config==null) {
                config = LoadConfig();
            }
            config.cxrLibraryConfig.logRootDirectory = Application.persistentDataPath;
            config.cxrLibraryConfig.dllRootDirectory = Path.GetFullPath("Packages/com.nvidia.cloudxr.client.unity-plugin/Runtime/Windows/");
            Log.level = config.debugLevel;
        }
        /// <inheritdoc />
        protected virtual void OnDisable()
        {
        }

        // ============================================================================
        //  Audio
        
        private float[] m_audioBuffer;
        private int m_n_samplesInBuffer = 0;
        private void _SetupAudio() {
            int length, count;
            AudioSettings.GetDSPBufferSize(out length,out count);
            Log.D($"Audio DSP buffer: block length {length}, block count {count}");
            int buffer_size = 
                length*count // samples in buffer
                *2 // number of channels
                *2 // have a double-size buffer.
                ;
            m_audioBuffer = new float[buffer_size];
        }

        private System.UInt64 m_filter_callcount = 0;

        private long latest = 0;
        void OnAudioFilterRead(float[] data, int channels) {
            long now = System.DateTime.Now.Ticks;
            // Log.W($"Entering filter read: {(int)((now-latest)/10000)} ms since last call");
            latest = now;
            if (client==null) return;

            // Step 1: copy the current buffers.
            client.DumpAudioQueue(ref m_audioBuffer, ref m_n_samplesInBuffer);


            // Log.W($"  ---------a- {m_filter_callcount}: {m_audioBuffer[0]} {m_n_samplesInBuffer} input samples, {channels} channels, {data.Length} output samples!");
            if (m_n_samplesInBuffer >= data.Length) {
                // Play the oldest audio as early as possible
                System.Array.Copy(m_audioBuffer,0,data,0,data.Length);
                // Copy the leftover forwards.
                int n_leftover = m_n_samplesInBuffer - data.Length;
                System.Array.Copy(m_audioBuffer,data.Length,m_audioBuffer,0,n_leftover);
                m_n_samplesInBuffer -= data.Length;
            }
            else {
                System.Array.Copy(m_audioBuffer,0,data,0,m_n_samplesInBuffer);
                m_n_samplesInBuffer = 0;
            }

            // Log.W($"  ---------b- {m_filter_callcount}: {m_n_samplesInBuffer} input samples, {channels} channels, {data.Length} output samples!");
            m_filter_callcount += 1;
            // if ( (m_filter_callcount%100) == 0)
            //     Log.W($"I'm playing audio!! {m_n_samplesInBuffer} input samples, {channels} channels, {data.Length} output samples!");
        }


        // ============================================================================
        //  Thread for sending poses
        private System.Threading.Thread poseUpdateThread;
        
        private bool quittingThreads = false;
        private double pollFrequencyHz = 250.0;
        public void PoseSendThread()
        {
            System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
            long pollPeriodTicks = (long)(
                (1.0/pollFrequencyHz) // Cycles/second > seconds/cycle
                * System.Diagnostics.Stopwatch.Frequency // Ticks / second
            );

            while (!quittingThreads)
            {
                long nextTick = (stopwatch.ElapsedTicks + pollPeriodTicks);
                nextTick -= (nextTick % pollPeriodTicks);

                // The work of this thread
                // The guards to make sure we don't call this when we shouldn't.
                if ( (state==S.running) && (client!=null) && (client.m_status == CloudXRStatus.connected) )
                {
                    // This call has the client "reach down" into the CxrUnityXRManager to get the pose,
                    // then "reach down" into the client library to immediately send it.
                    client.SendPoses();
                }


                long afterWork = stopwatch.ElapsedTicks;
                if (afterWork > nextTick)
                    continue;

                // Determine how long until the next tick
                long sleepTimeTicks = nextTick - afterWork;
                // Convert sleep time from ticks to milliseconds (rounded down)
                int sleepTimeMillis = (int)(sleepTimeTicks / (System.Diagnostics.Stopwatch.Frequency / 1e3));
                // Sleep until the next tick
                System.Threading.Thread.Sleep(sleepTimeMillis);
            }
        }
        // ============================================================================
        //  Platform detection

        public XrPlatform? GetXrPlatform() {
            return m_unityXrManager.GetXrPlatform();
        }
        public uint GetUnityResolutionWidth() {
            return m_unityXrManager.getEyeTextureWidth();
        }
        public void SetUnityResolutionScaling(float scaleFactor) {
            m_unityXrManager.SetUnityResolutionScaling(scaleFactor);
        }

    }
}

And one more thing, please provide a documentation for all the classes that you have used in the Unity plugin

I got one more. I build the apk on meta quest but CXR simply doesnt work. On checking adb logcat the first error I got was this DllNotFoundException:

2024-11-22 14:15:22.506 31040 31063 Error Unity DllNotFoundException: Unable to load DLL ‘libCloudxrClientlibCsharp.so’. Tried the load the following dynamic libraries: Unable to load dynamic library ‘libCloudxrClientlibCsharp.so’ because of 'Failed to open the requested dynamic library (0x06000000) dlerror() = dlopen failed: library “libc++_shared.so” not found: needed by /data/app/~~9mGqLiALSw6dJ4pLWgagyg==/com.TataElxsi.CXR-6sZ69lr3Dr__N_iyTdyv2g==/lib/arm64/libCloudXRClient.so in namespace classloader-namespace

What am I doing wrong?

IMPORTANT: I want to mention that I have enabled “CloudXR tuned pose capture”, still im getting this

Sharing my Unity side client connection script, @AndreusNvidius kindly review:

using CloudXR;

using CloudXrClientWrapper;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using CloudXrClientWrapper;

using static CloudXR.CloudXRManager;
 
using Unity.VisualScripting.FullSerializer;

using System;

using TMPro;

using UnityEngine.UI;

using static System.Net.Mime.MediaTypeNames;
 
public class CXRCustomImplementation : CloudXRManager

{

    CloudXRManager cxrManager;
 
    //public delegate void c_OnStatusChanged(object sender, StatusEventArgs e);

    public delegate void c_OnStatusChanged(object sender, CloudXRManager.StatusChangeArgs e);

    //public c_OnStatusChanged c_OnStatusChanged_Declaration;
 
    public event c_OnStatusChanged c_onStatusChanged_Event_Var;
 
    public UnityEngine.UI.Text debugText;
 
    // State machine internal code

    private S state = S.dormant;

    public S currentState

    {

        get { return state; }

    }
 
    // Input bindings

    private CxruDeviceBinding[] m_bindings = null;

    public void SetBindings(CxruDeviceBinding[] bindings)

    {

        m_bindings = bindings;

    }
 
    // Start is called before the first frame update

    void Start()

    {

        cxrManager = Camera.main.GetComponent<CloudXRManager>();

        OnConnectButtonClick();//for now

                               //__statusChanged += OnCxrStatusChange;

    }
 
    
 
    //protected override void Update()

    //{

    //    base.Update();

    //}

    public void OnConnectButtonClick()

    {

        ConfigureCloudXR();

    }
 
    /// <summary>

    /// main function of this script (step by step CloudXR connection setup)

    /// </summary>

    void ConfigureCloudXR()

    {

        cxrManager.config = new CxruConfig();

        cxrManager.config = GetCustomConfig();

        cxrManager.statusChanged += OnCxrStatusChange;

        ConnectToServer();

        //statusChanged += OnStatusChanged;//how to pass args in this

        c_onStatusChanged_Event_Var += OnStatusChangedCallbackFunction;

    }
 
    
 
    /// <summary>

    /// the skeleton of this function is simply copy pasted from GetDefaultConfig() of CloudXRManager.cs

    /// </summary>

    /// <returns></returns>

    CxruConfig GetCustomConfig()

    {

        // Initialize with non-default defaults.

        // bool defaults to false; int/uint/float to 0.

        CxruConfig newConfig = new CxruConfig();

        newConfig.cxrLibraryConfig.cxrRecieverConfig.logMaxSizeKB = -1;

        newConfig.cxrLibraryConfig.cxrRecieverConfig.logMaxAgeDays = -1;
 
        // config.cxrLibraryConfig.cxrDebugConfig.enableAImageReaderDecoder = true;

        newConfig.cxrLibraryConfig.cxrDebugConfig.outputLinearRGBColor = false;
 
        newConfig.cxrLibraryConfig.cxrDeviceConfig.receiveAudio = true;

        newConfig.cxrLibraryConfig.cxrDeviceConfig.sendAudio = false;

        newConfig.cxrLibraryConfig.cxrDeviceConfig.maxResFactor = 1f;

        newConfig.cxrLibraryConfig.cxrDeviceConfig.foveatedScaleFactor = 50;

        newConfig.cxrLibraryConfig.cxrDeviceConfig.maxClientQueueSize = 0f; // Arjun said on call 2022-08-02 that this is correct to invoke the default

        newConfig.cxrLibraryConfig.cxrDeviceConfig.angularVelocityInDeviceSpace = true;

        newConfig.cxrLibraryConfig.cxrDeviceConfig.maxVideoBitrateKbps = 0; // Use library default
 
        newConfig.cxrLibraryConfig.cxrConnectionConfig.clientNetwork = cxrNetworkInterface.cxrNetworkInterface_WiFi24Ghz;

        newConfig.cxrLibraryConfig.cxrConnectionConfig.topology = cxrNetworkTopology.cxrNetworkTopology_LAN;
 
        newConfig.debugLevel = DebugLevel.Info;

        newConfig.doLDAT = true;
 
        newConfig.serverAddress = "10.100.27.73";//comments: take from ip field

        return newConfig;

    }
 
    /// <summary>

    /// just a copy paste of the same function in CxruClientSampleAutoconnect.cs

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    void OnCxrStatusChange(object sender, CloudXRManager.StatusChangeArgs e)

    {

        Debug.Log($"event fired! {e.new_status}");
 
        if (e.new_status == CloudXRManager.S.error)

        {

            Debug.Log($"Oh no! Error!");

            if (e.result != null)

            {

                Debug.Log($"{e.result.message}, cxr error {e.result.api_cxrError}: '{e.result.api_cxrErrorString}'");

            }

        }
 
    }
 
    private void OnStatusChangedCallbackFunction(object sender, StatusChangeArgs e)

    {

        Debug.Log("Inside OnStatusChangedCallbackFunction");

        switch (e.new_status)

        {

            case S.connecting:

                debugText.text = "connecting";

                break;

            case S.running:

                debugText.text = "running";

                break;

            case S.disconnecting:

                debugText.text = "disconnecting";

                break;

            case S.dormant:

                debugText.text = "dormant";

                break;

            case S.error:

                debugText.text = "error " + e.result.api_cxrErrorString + "\t\t\t" + e.result.message;

                break;

            case S.configuring:

                debugText.text = "configuring ";

                break;
 
        }
 
    }
 
    void ConnectToServer()

    {

        Debug.Log("Attempting to connect to server");

        //a.Set server_ip:

        cxrManager.server_ip = "10.100.27.73";//serverAddress; // IP string like "127.0.0.1"
 
        //set bindings

        cxrManager.SetBindings(CxruSampleBindings.oculusTouchBindings);

        //connect

        cxrManager.Connect();

    }
 
    private void OnStatusChanged(object sender, StatusChangeArgs e)

    {

        Debug.Log("status changed!: " + e.new_status.ToString() + "\n" + e.result.ToString() + "\n" + e.previous_status.ToString());

        //debugText.text = e.new_status.ToString() + "\n" + e.result.ToString() + "\n" + e.previous_status.ToString();

        debugText.text = "abc";//e.new_status.ToString();

    }
 
}

The real function to check is ConfigureCloudXR()

Edit: also sharing the unity logs (from meta quest device)
logcat.txt (1.4 MB)

just wanted to update everyone, I got the unity plugin working. Im able to stream cloud xr successfully