Hardware / Software
-
Device: Jetson Orin Nano Super (8GB)
-
JetPack: 6.2.2
-
DeepStream: 7.1
-
CUDA: 12.6
-
TensorRT: 10.3
-
Pipeline framework: pyservicemaker (Python)
-
Power mode: MAXN_SUPER
Problem
I have a DeepStream pipeline that runs inference + NvDCF tracking and writes an H.264 .mkv file to disk.
The pipeline behaves differently depending on whether Xorg is running:
| Mode | systemd target | DISPLAY | Result |
|---|---|---|---|
| Desktop | graphical.target (Xorg running) |
:0 |
Valid playable file with OSD overlays |
| Headless | multi-user.target (no Xorg) |
unset | 0-byte file, but pipeline runs at full FPS and inference/tracking are correct |
Inference and tracking work correctly in both modes. The failure only affects the encode-to-file branch.
There are no bus errors:
-
Pipeline reaches
PLAYING -
FPS is normal
-
File handle is created
-
Output file remains 0 bytes for the entire run
Pipeline (save branch)
… → nvstreamdemux → queue → nvdsosd → tee
├─ queue → nv3dsink (optional display)
└─ queue → nvvideoconvert → x264enc → h264parse → matroskamux → filesink
In desktop mode, nv3dsink creates an NVIDIA EGL context which appears to be shared through GstContext. nvvideoconvert then successfully maps NVMM buffers to system memory.
In headless mode, there is no display sink and no EGL context provider in the pipeline.
Current understanding of the failure
nvvideoconvert converting from:
video/x-raw(memory:NVMM) → video/x-raw
appears to require EGLImage mapping.
On Jetson, EGLImage creation seems to depend on an NVIDIA EGL context backed by Xorg.
Without that context:
-
nvvideoconvertaccepts buffers -
no downstream buffers are produced
-
upstream queues eventually drop frames
-
filesinknever receives encoded data -
no explicit error is posted on the bus
CUDA-only paths (TensorRT inference + NvDCF tracking) continue working because they remain entirely in GPU memory.
What I tried
1. Removing nvdsosd
No change. Output file still remains 0 bytes.
2. compute-hw=1 on nvvideoconvert
Attempted to force CUDA compute instead of VIC.
Pipeline fails to start. The property does not appear valid for nvvideoconvert on Orin Nano under DS 7.1.
3. Xvfb (DISPLAY=:99)
This produces:
nvbufsurface: Failed to create EGLImage
Xvfb provides Mesa EGL rather than NVIDIA EGL. Once DISPLAY is set, NVIDIA plugins appear to attempt EGL initialization against the wrong provider.
4. External recorder path
Using OpenCV + FFmpeg separately from DeepStream works, but requires reading the source twice and bypasses the DeepStream encode path entirely.
Questions
1. Supported headless NVMM → system-memory conversion
Is there a supported way to make nvvideoconvert produce system-memory output in a fully headless environment on Jetson Orin Nano + DeepStream 7.1?
Specifically:
-
Can NVIDIA EGL be initialized without Xorg?
-
Is there a CUDA/VIC path that avoids EGLImage usage entirely?
2. Recommended headless encode topology
Is there a known-good save pipeline for headless Orin Nano deployments?
For example:
nvvideoconvert ! video/x-raw(memory:NVMM),format=I420 \
! nvv4l2h264enc ! h264parse ! matroskamux ! filesink
Would keeping everything in NVMM avoid the EGLImage dependency?
Orin Nano does not have NVENC, so I am not sure whether nvv4l2h264enc is actually usable on this platform.
If software encoding (x264enc) is the expected path, what is the supported way to perform NVMM → CPU memory conversion headlessly?
3. Documentation
Is the EGL/Xorg dependency for NVMM → system-memory conversion documented anywhere?
The failure mode is difficult to debug because:
-
pipeline reaches
PLAYING -
FPS remains healthy
-
no bus errors are emitted
-
only the output file is empty
A warning from nvvideoconvert when EGLImage creation fails would make this much easier to diagnose.
4. Recommended workaround
Is running a minimal Xorg session purely to host the NVIDIA EGL context the recommended workaround for headless Jetson deployments?
If yes:
-
is there an official minimal Xorg configuration?
-
is there a recommended
systemdservice/unit for this setup? -
can this be done without a physical monitor attached?
Minimal repro
gst-launch-1.0 \
filesrc location=in.mp4 ! qtdemux ! h264parse ! nvv4l2decoder \
! m.sink_0 nvstreammux name=m batch-size=1 width=1280 height=720 \
! nvvideoconvert ! ‘video/x-raw,format=I420’ \
! x264enc tune=zerolatency speed-preset=ultrafast bitrate=4000 \
! h264parse ! matroskamux ! filesink location=out.mkv
Behavior:
-
graphical.targetwithDISPLAY=:0→ valid playable file -
multi-user.targetwith noDISPLAY→ 0-byte file with no errors
Any guidance on the supported headless encode path for Jetson Orin Nano + JetPack 6.2.2 + DeepStream 7.1 would be appreciated.