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

Aaron Angulo ·

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.

Aarón Angulo, Co-Founder & CEO at ProventusNova

Written by

Aarón Angulo

Co-Founder & CEO · ProventusNova

Obsessed with client outcomes. Aarón ensures every engagement delivers real results, on time, on scope, no exceptions.

Connect on LinkedIn