[Jetson Orin NX + Multi-Cam] Can't Reach 30 FPS on 4 ZEDs – Streaming to External GPU (4060Ti)

Hi all,

I’m working on a multi-camera streaming setup using 4 ZED cameras connected via GMSL2 to a Jetson Orin NX 16GB running JetPack 6.0.
My goal is to stream 1080p@30FPS per camera to a desktop PC equipped with a 4060Ti, which handles the processing. I’m not doing any depth computation on the Jetson – it’s strictly acting as a streaming source.

The Jetson is configured with:

  • sudo nvpmodel -m 0
  • sudo jetson_clocks
  • JetPack 6.0

I’m using H.265 streaming with bitrate = 5000, chunk_size = 4096, and adaptive_bitrate = true.

Here is the simplified version of the streaming code I’m using:

#include <sl/Camera.hpp>
#include <thread>
#include <vector>
#include <atomic>
#include <csignal>
#include <iostream>

using namespace sl;
using namespace std;

static atomic<bool> exit_flags[4];

void signalHandler(int) {
    for (auto &flag : exit_flags) flag.store(true);
}

void streamThread(int camID, int port) {
    Camera zed;
    InitParameters init_params;
    init_params.camera_resolution = RESOLUTION::HD1080;
    init_params.depth_mode = DEPTH_MODE::NONE;
    init_params.camera_fps = 30;
    init_params.input.setFromCameraID(camID);

    if (zed.open(init_params) != ERROR_CODE::SUCCESS) return;

    StreamingParameters stream_params;
    stream_params.port = port;
    stream_params.codec = STREAMING_CODEC::H265;
    stream_params.bitrate = 5000;
    stream_params.chunk_size = 4096;
    stream_params.adaptative_bitrate = true;

    if (zed.enableStreaming(stream_params) != ERROR_CODE::SUCCESS) {
        zed.close();
        return;
    }

    RuntimeParameters runtime_params;
    runtime_params.enable_depth = false;

    while (!exit_flags[camID].load()) {
        auto t0 = chrono::high_resolution_clock::now();
        if (zed.grab(runtime_params) == ERROR_CODE::SUCCESS) {
            auto t1 = chrono::high_resolution_clock::now();
            auto ms = chrono::duration_cast<chrono::milliseconds>(t1 - t0).count();
            cout << "[Cam" << camID << "] Grab time: " << ms << " ms" << endl;
        }
    }

    zed.disableStreaming();
    zed.close();
}

int main() {
    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    const int numCams = 4;
    const int basePort = 30000;
    vector<thread> threads;

    for (int i = 0; i < numCams; ++i) {
        int port = basePort + i * 2;
        threads.emplace_back(streamThread, i, port);
    }

    for (auto &t : threads) t.join();
    return EXIT_SUCCESS;
}

Even with all depth computation disabled, the grab() times fluctuate between 18 ms and 49 ms, meaning I never consistently hit 30 FPS per camera. On average, each camera sits around 22–25 FPS. Beyond 60 FPS, the bus becomes unstable and images get corrupted (as expected).

I’ve tested:

  • Raising thread priority with SCHED_FIFO
  • Adding slight initial delays to stagger grabs
  • Different bitrates and codecs (H.264 vs H.265)

But still, I can’t seem to push to 30 FPS across all 4 cameras simultaneously at 1080p.

Is this a hard limit due to GMSL2/CSI or encoder throughput on the Orin NX?

Thanks in advance for any help or insights!
If anyone has a working example of 4x 1080p@30FPS streaming from Orin NX, I’d love to benchmark it.

Have you tried using larger chunk sizes? Also what’s your networking setup? In the past I’ve had issues caused by a 100Mbps ethernet cable that was bottle-necking a system that otherwise had 2.5Gbps gear.

I haven’t completed the work on this system, but am also very interested in the performance and latency you observe with this streaming setup. I also want to offload depth processing to a more powerful x86 computer that’s part of my system.

Have you noticed a performance difference between cpp and python?

1 Like

Hi @Cubia
The ZED SDK team tested your code to check that everything is OK.

We are not at 30fps at each frame, but when measuring on a moving average with a window of size 10, the FPS is stable at 30 Hz.

We tested your code on a ZED Box Orin NX 16 without jetson_clocks and we confirm 30 FPS on average.

With the current information we cannot understand why you are limited to 22-25 FPS on average.

Hi, thanks everyone for the responses.
I am still limited at those FPS, but i noticed that by removing one cam i obtain 30 FPS for every camera.
Can it be related to cables length since i’m using 15mt gmsl2? Also my network is probably not powerful as it should (i’ts a 2.4GHz, i will surely try with phone hotspot that supports 5GHz).
Moreover, having the HDMI connected to a display could make it worse?