Terminal showing gst-launch-1.0 pipeline running on Jetson Orin with camera capture and hardware encode
jetsongstreamernvarguscamerasrcnvvidconvv4l2srcpipelinecamera

GStreamer pipeline examples for Jetson: nvarguscamerasrc, nvvidconv, encode, and decode

Andres Campos ·

GStreamer on Jetson uses NVIDIA-specific elements for hardware-accelerated camera capture, format conversion, and encode/decode. These elements — nvarguscamerasrc, nvvidconv, nvv4l2h264enc, nvv4l2decoder — have different properties and caps requirements than their generic Linux equivalents. This post is a practical reference for the GStreamer pipelines that actually work on Jetson Orin, with copy-paste commands for the most common use cases.

Key Insights

  • NVMM caps (video/x-raw(memory:NVMM)) keep frames in GPU memory between NVIDIA elements — always use them between nvarguscamerasrc, nvvidconv, and nvv4l2h264enc
  • nvarguscamerasrc is for ISP-processed camera capture; v4l2src is for raw sensor frames
  • kmssink works without X or Wayland — use it for headless display output on embedded setups
  • nvv4l2h264enc and nvv4l2decoder use Jetson’s hardware encode/decode engines; avenc_h264 and avdec_h264 are software fallbacks
  • gst-inspect-1.0 and GST_DEBUG are your primary debugging tools — inspect before troubleshooting

Prerequisites

Install NVIDIA’s GStreamer plugins:

sudo apt install nvidia-l4t-gstreamer gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-tools

Verify NVIDIA elements are available:

gst-inspect-1.0 nvarguscamerasrc
gst-inspect-1.0 nvvidconv
gst-inspect-1.0 nvv4l2h264enc
gst-inspect-1.0 nvv4l2decoder

If any of these fail, the nvidia-l4t-gstreamer package wasn’t installed or its plugins didn’t load. Check gst-inspect-1.0 --gst-plugin-path /usr/lib/aarch64-linux-gnu/gstreamer-1.0/.

Camera capture pipelines

Basic display test:

gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
  'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
  nvvidconv ! 'video/x-raw,format=BGRx' ! \
  videoconvert ! autovideosink

Headless — capture to file:

gst-launch-1.0 nvarguscamerasrc sensor-id=0 num-buffers=300 ! \
  'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
  nvv4l2h264enc ! h264parse ! qtmux ! \
  filesink location=/tmp/capture.mp4

Get ISP-processed frames as NV12 for OpenCV or inference:

gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
  'video/x-raw(memory:NVMM),width=1280,height=720,framerate=30/1' ! \
  nvvidconv ! 'video/x-raw,format=NV12' ! \
  appsink name=sink max-buffers=1 drop=true

Check available sensor IDs:

gst-launch-1.0 nvarguscamerasrc ! fakesink -v 2>&1 | grep "Available Sensor"

v4l2src (raw V4L2 path)

Basic display (format depends on sensor):

gst-launch-1.0 v4l2src device=/dev/video0 ! \
  'video/x-raw,format=YUY2,width=1920,height=1080,framerate=30/1' ! \
  videoconvert ! autovideosink

Display via KMS/DRM without X server:

gst-launch-1.0 v4l2src device=/dev/video0 ! \
  'video/x-raw,format=YUY2,width=1920,height=1080,framerate=30/1' ! \
  videoconvert ! kmssink

Check what formats your camera supports:

v4l2-ctl --list-formats-ext -d /dev/video0

Raw capture to file (useful for debugging sensor output):

gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=30 ! \
  'video/x-raw,format=RG10,width=1920,height=1080' ! \
  filesink location=/tmp/raw_frames.bin

Hardware encode

H.264 encode

Camera → H.264 file:

gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
  'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
  nvv4l2h264enc bitrate=8000000 ! h264parse ! \
  qtmux ! filesink location=output.mp4

Camera → H.264 UDP stream (for remote viewing):

# Sender (Jetson)
gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
  'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
  nvv4l2h264enc ! h264parse ! \
  rtph264pay ! udpsink host=192.168.1.100 port=5000

# Receiver (laptop)
gst-launch-1.0 udpsrc port=5000 ! \
  'application/x-rtp,encoding-name=H264,payload=96' ! \
  rtph264depay ! avdec_h264 ! autovideosink

H.265 encode

H.265 typically achieves the same quality at half the bitrate:

gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
  'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
  nvv4l2h265enc bitrate=4000000 ! h265parse ! \
  qtmux ! filesink location=output.mp4

nvv4l2h264enc key properties:

  • bitrate — target bitrate in bps (default: 4000000)
  • maxperf-enable — set to true for maximum throughput at higher power
  • preset-level — 1 (ultra-fast) to 4 (best quality), default 3

Hardware decode

MP4 file → display:

gst-launch-1.0 filesrc location=video.mp4 ! \
  qtdemux ! h264parse ! nvv4l2decoder ! \
  nvvidconv ! 'video/x-raw,format=BGRx' ! \
  videoconvert ! autovideosink

H.265 decode:

gst-launch-1.0 filesrc location=video.mp4 ! \
  qtdemux ! h265parse ! nvv4l2decoder ! \
  nvvidconv ! autovideosink

Note: nvv4l2decoder outputs NVMM-format frames. Connect directly to nvvidconv (not videoconvert) to stay in the hardware path.

nvvidconv — format conversion and scaling

nvvidconv is Jetson’s hardware video converter. Use it between NVIDIA elements for format conversion and scaling without CPU involvement.

Convert YUY2 → BGRx:

gst-launch-1.0 v4l2src device=/dev/video0 ! \
  'video/x-raw,format=YUY2,width=1920,height=1080' ! \
  nvvidconv ! 'video/x-raw,format=BGRx,width=1920,height=1080' ! \
  videoconvert ! autovideosink

Scale and convert in one step:

gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
  'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
  nvvidconv ! 'video/x-raw(memory:NVMM),width=640,height=360' ! \
  nvv4l2h264enc ! h264parse ! qtmux ! filesink location=scaled.mp4

Important: When connecting two NVIDIA elements, add (memory:NVMM) to the caps between them:

# Correct — stays in GPU memory
! nvvidconv ! 'video/x-raw(memory:NVMM),format=NV12' ! nvv4l2h264enc

# Wrong — forces CPU copy
! nvvidconv ! 'video/x-raw,format=NV12' ! nvv4l2h264enc

Multi-camera pipelines

View two cameras side by side:

gst-launch-1.0 \
  nvarguscamerasrc sensor-id=0 name=cam0 ! \
    'video/x-raw(memory:NVMM),width=1280,height=720,framerate=30/1' ! \
    nvvidconv ! 'video/x-raw,format=BGRx,width=640,height=360' ! videoconvert ! \
    compositor name=mix sink_0::xpos=0 sink_0::ypos=0 sink_1::xpos=640 sink_1::ypos=0 ! \
    autovideosink \
  nvarguscamerasrc sensor-id=1 ! \
    'video/x-raw(memory:NVMM),width=1280,height=720,framerate=30/1' ! \
    nvvidconv ! 'video/x-raw,format=BGRx,width=640,height=360' ! videoconvert ! \
    mix.

Record both cameras independently:

gst-launch-1.0 \
  nvarguscamerasrc sensor-id=0 ! \
    'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
    nvv4l2h264enc ! h264parse ! qtmux ! filesink location=cam0.mp4 \
  nvarguscamerasrc sensor-id=1 ! \
    'video/x-raw(memory:NVMM),width=1920,height=1080,framerate=30/1' ! \
    nvv4l2h264enc ! h264parse ! qtmux ! filesink location=cam1.mp4

Debugging pipelines

Inspect element properties:

gst-inspect-1.0 nvarguscamerasrc
gst-inspect-1.0 nvv4l2h264enc

Verbose caps negotiation:

gst-launch-1.0 -v nvarguscamerasrc ! fakesink 2>&1 | head -50

Enable debug logging:

# Log all elements at level 3
GST_DEBUG=3 gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! fakesink

# Log specific elements
GST_DEBUG=nvarguscamerasrc:5,nvvidconv:4 gst-launch-1.0 ...

Check pipeline state manually:

# Add -v to see state changes
gst-launch-1.0 -v nvarguscamerasrc sensor-id=0 ! \
  'video/x-raw(memory:NVMM)' ! nvvidconv ! autovideosink

Common pipeline errors:

ErrorCauseFix
”No such element: nvarguscamerasrc”nvidia-l4t-gstreamer not installedsudo apt install nvidia-l4t-gstreamer
”Internal data flow error”Buffer backpressureAdd ! queue after the source
”nvarguscamerasrc: No cameras available”nvargus-daemon not runningsudo systemctl start nvargus-daemon
Pipeline hangs at PLAYINGNVMM path brokenCheck caps have (memory:NVMM) between NVIDIA elements
”Cannot identify /dev/video0”Camera not probedCheck v4l2-ctl --list-devices

For camera driver bring-up that these pipelines depend on, see CSI camera driver on Jetson: V4L2, Argus, and IMX sensor bring-up. For Argus-specific setup including nvargus-daemon, see NVIDIA Argus API camera driver on Jetson. For pipeline performance issues — nvvidconv throughput collapse under multiple processes — see nvvidconv performance with multiple GStreamer processes on Jetson.

FAQ

Why does nvarguscamerasrc say “No such element or plugin”?

The nvidia-l4t-gstreamer package isn’t installed. Install it with: sudo apt install nvidia-l4t-gstreamer. Also verify gst-inspect-1.0 nvarguscamerasrc returns the element description. If it still fails after install, nvargus-daemon isn’t running — start it with sudo systemctl start nvargus-daemon.

What is the difference between v4l2src and nvarguscamerasrc on Jetson?

v4l2src reads raw frames directly from the V4L2 kernel driver — no ISP processing. nvarguscamerasrc routes through the nvargus-daemon and Jetson ISP, providing auto-exposure, auto-white-balance, and hardware noise reduction. Use nvarguscamerasrc for production pipelines that need ISP output; use v4l2src when you need raw Bayer frames or have a sensor that isn’t Argus-compatible.

What does “video/x-raw(memory:NVMM)” mean in a Jetson GStreamer pipeline?

NVMM keeps frame buffers in GPU memory, avoiding a CPU copy between NVIDIA hardware elements. When connecting nvarguscamerasrc to nvvidconv, or nvvidconv to nvv4l2h264enc, always use NVMM caps to maintain the hardware-accelerated path. Without NVMM, frames are copied through system RAM, adding latency and CPU load.

Why does my GStreamer pipeline stall or produce “Internal data flow error”?

Usually buffer backpressure — a downstream element isn’t consuming frames as fast as they arrive. Add ! queue between the source and a slow downstream element. If the pipeline stops after a few seconds, check for missing NVMM caps — this often causes stalls in the format conversion stage.

How do I display a Jetson camera feed without X or Wayland (headless)?

Use kmssink for DRM/KMS direct rendering without a display server: gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! kmssink. Or pipe to a file or network stream instead of a display sink.


NVIDIA Jetson Expert Support

Stuck on a Jetson bring-up?

We've debugged this failure mode before. BSP, device tree, camera pipelines, OTA — most blockers clear in the first session. No long retainers. No guessing.

Frequently Asked Questions

Why does nvarguscamerasrc say 'No such element or plugin'?

The nvidia-l4t-gstreamer package isn't installed. Install it with: sudo apt install nvidia-l4t-gstreamer. Also verify gst-inspect-1.0 nvarguscamerasrc returns the element description. If it still fails, the nvargus-daemon isn't running — start it with sudo systemctl start nvargus-daemon.

What is the difference between v4l2src and nvarguscamerasrc on Jetson?

v4l2src reads raw frames directly from the V4L2 kernel driver — no ISP processing. nvarguscamerasrc routes through the nvargus-daemon and Jetson ISP, providing auto-exposure, auto-white-balance, and hardware noise reduction. Use nvarguscamerasrc for production camera pipelines that need ISP output; use v4l2src when you need raw Bayer frames or have a sensor that isn't Argus-compatible.

What does 'video/x-raw(memory:NVMM)' mean in a Jetson GStreamer pipeline?

NVMM (NVIDIA Memory Management) keeps frame buffers in GPU memory, avoiding a CPU copy between NVIDIA hardware elements. When connecting nvarguscamerasrc to nvvidconv, or nvvidconv to nvv4l2h264enc, always use NVMM caps to maintain the hardware-accelerated path. Without NVMM, frames are copied through system RAM, adding latency and CPU load.

Why does my GStreamer pipeline stall or produce Internal data flow error?

Usually a buffer backpressure problem — a downstream element isn't consuming frames as fast as they arrive. Add '! queue' between the source and a slow downstream element. If the pipeline stops after a few seconds, check for nvvidconv NVMM caps — missing NVMM often causes stalls in the format conversion stage.

How do I display a Jetson camera feed without X or Wayland (headless)?

Use kmssink for DRM/KMS direct rendering without a display server: gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! kmssink. Or pipe to a file or network stream instead of a display sink. nvarguscamerasrc also works headless — route to filesink or udpsink instead of autovideosink.

Andrés Campos, Co-Founder & CTO at ProventusNova

Written by

Andrés Campos

Co-Founder & CTO · ProventusNova

8 years deep in embedded systems — from underwater ROVs to edge AI. Andrés leads every technical delivery personally.

Connect on LinkedIn