NVIDIA Argus API camera driver on Jetson: setup, streaming, and debugging
The NVIDIA Argus API is how most production Jetson camera pipelines work. It sits above the V4L2 kernel driver and provides ISP processing — auto-exposure, auto-white-balance, HDR — without requiring you to build a custom ISP pipeline. If your camera produces blurry, poorly-exposed frames with raw V4L2 capture, Argus is usually the solution. This post covers how to get Argus working, what the API looks like, and what to do when it doesn’t cooperate.
Key Insights
- Argus and V4L2 are not alternatives — they’re layers. The kernel driver (V4L2) must be working before Argus can do anything
- nvargus-daemon is required — it’s a separate system service that manages the ISP hardware; if it’s not running, all Argus calls fail immediately
- The ISP adds real value: AE, AWB, HDR, and denoise are handled automatically once Argus is running, with no additional application code
- LibArgus C++ API gives you full control;
nvarguscamerasrc(GStreamer) gives you fast integration with existing pipelines - “No cameras available” is almost always either a dead daemon or a driver that didn’t register with the tegracam framework
V4L2 vs Argus: which layer do you actually need?
Both operate on the same kernel driver. The kernel driver exposes a V4L2 subdev and video node. Argus — via nvargus-daemon — uses the V4L2 interface internally, processes frames through the ISP, and hands ISP-corrected output to your application.
| V4L2 | Argus (LibArgus / nvarguscamerasrc) | |
|---|---|---|
| Frame format | Raw Bayer, YUV | ISP-processed NV12, RGBA |
| ISP (AE, AWB, HDR) | No | Yes |
| GStreamer element | v4l2src | nvarguscamerasrc |
| Headless | Yes | Yes |
| Multi-camera sync | Manual | Built-in via sensor mode |
| NVIDIA-only | No | Yes |
The practical rule: if you need ISP output for a machine vision or AI inference pipeline, use Argus. If you need raw Bayer frames for custom processing or compatibility with non-NVIDIA tooling, use V4L2 directly.
Setting up nvargus-daemon
The daemon is installed with the nvidia-l4t-libargus package (included in JetPack). On JetPack 6, it’s managed by systemd:
# Check if it's running
systemctl status nvargus-daemon
# Start it
sudo systemctl start nvargus-daemon
# Enable it at boot
sudo systemctl enable nvargus-daemon
In headless setups (no display manager), the daemon often isn’t started automatically because it has a display dependency in older JetPack releases. On JetPack 6, you can add it to a startup script or systemd target manually if it doesn’t start on its own.
Verify the daemon is up before running any Argus code:
ps aux | grep nvargus
# Should show: /usr/sbin/nvargus-daemon
GStreamer pipelines with nvarguscamerasrc
nvarguscamerasrc is the GStreamer source element that uses libargus internally. It’s the fastest way to test your camera through the Argus path.
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=output.mp4
Multiple cameras (sensor-id selects the camera):
# Camera 0
gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! \
'video/x-raw(memory:NVMM),width=1920,height=1080' ! nvvidconv ! autovideosink &
# Camera 1
gst-launch-1.0 nvarguscamerasrc sensor-id=1 ! \
'video/x-raw(memory:NVMM),width=1920,height=1080' ! nvvidconv ! autovideosink
The (memory:NVMM) caps keep frames in GPU memory between NVIDIA elements, avoiding a CPU copy. Always use NVMM caps between nvarguscamerasrc and nvvidconv.
Check available sensor IDs:
gst-launch-1.0 nvarguscamerasrc ! fakesink -v 2>&1 | grep "camera ID"
ISP features Argus provides
Once the daemon is running, the ISP processes every frame automatically. Features available through the LibArgus API or nvarguscamerasrc properties:
Auto-exposure (AE): The ISP adjusts exposure time and gain to maintain target brightness. Enabled by default. Override with exposuretimerange and gainrange properties on nvarguscamerasrc.
Auto-white-balance (AWB): Color correction applied per-frame. Enabled by default. Override with wbmode property.
ISP digital gain (IDG): Additional gain applied after analog sensor gain. Useful for low-light without changing frame rate.
HDR: Supported on sensors that implement multi-exposure capture (sensor-specific — check your sensor driver’s mode table).
Noise reduction: Temporal and spatial noise reduction applied by the ISP. Controlled via the LibArgus API IDenoiseSettings interface.
LibArgus C++ API basics
For applications that need direct ISP control beyond what nvarguscamerasrc exposes:
#include <Argus/Argus.h>
#include <EGLStream/EGLStream.h>
using namespace Argus;
// 1. Create the camera provider
UniqueObj<CameraProvider> cameraProvider(CameraProvider::create());
ICameraProvider* iCameraProvider = interface_cast<ICameraProvider>(cameraProvider);
// 2. Get camera devices
std::vector<CameraDevice*> cameraDevices;
iCameraProvider->getCameraDevices(&cameraDevices);
CameraDevice* cameraDevice = cameraDevices[0];
// 3. Create capture session
UniqueObj<CaptureSession> captureSession(
iCameraProvider->createCaptureSession(cameraDevice));
ICaptureSession* iCaptureSession = interface_cast<ICaptureSession>(captureSession);
// 4. Create output stream (EGLStream for GPU consumption)
UniqueObj<OutputStreamSettings> streamSettings(
iCaptureSession->createOutputStreamSettings(STREAM_TYPE_EGL));
UniqueObj<OutputStream> outputStream(
iCaptureSession->createOutputStream(streamSettings.get()));
// 5. Create request and submit
UniqueObj<Request> request(iCaptureSession->createRequest(CAPTURE_INTENT_PREVIEW));
IRequest* iRequest = interface_cast<IRequest>(request);
iRequest->enableOutputStream(outputStream.get());
// Start repeating capture
iCaptureSession->repeat(request.get());
The LibArgus headers live in /usr/include/Argus/. Link against -lnvargus. Full API documentation is in the JetPack SDK at /usr/src/jetson_multimedia_api/argus/.
Common Argus errors
“No cameras available”
The sensor isn’t registered with Argus. Check in order: (1) daemon running? systemctl status nvargus-daemon; (2) kernel driver probed? dmesg | grep -i imx or your sensor name; (3) driver implements tegracam interface? Reference drivers do; custom/ported drivers may not.
“Failed to create capture session”
The camera device exists but the ISP pipeline couldn’t be initialized. Usually a kernel driver probe issue — the driver probed but didn’t complete ISP configuration. Check dmesg during daemon start for VI or NVCSI errors.
“nvarguscamerasrc: Internal data flow error”
Frame delivery failure mid-stream. Usually a NVMM buffer exhaustion — either not consuming frames fast enough, or a downstream element isn’t releasing buffers. Add ! queue between nvarguscamerasrc and the next element.
“Cannot open camera 0” / wrong sensor-id Sensor IDs are assigned at boot based on DTS order. If you have two cameras but only one is connected, sensor-id=0 may not be camera 0 by DTS position. Use the sensor ID inspection command above to verify which IDs are active.
Debugging checklist
# 1. Daemon running?
systemctl status nvargus-daemon
# 2. Kernel driver loaded and probed?
lsmod | grep -i imx # replace with your sensor module name
dmesg | grep -i "probe"
# 3. V4L2 node exists?
v4l2-ctl --list-devices
# 4. Media pipeline intact?
media-ctl -d /dev/media0 --print-topology
# 5. GStreamer plugins available?
gst-inspect-1.0 nvarguscamerasrc
# 6. Test with minimal pipeline
gst-launch-1.0 nvarguscamerasrc num-buffers=10 ! fakesink -v
If step 5 fails (“No such element”), the nvidia-l4t-gstreamer package isn’t installed: sudo apt install nvidia-l4t-gstreamer.
If step 6 hangs at “Setting pipeline to PLAYING” without error, the daemon is running but ISP initialization stalled — reboot the daemon and check dmesg for VI probe errors.
For the underlying kernel driver setup that Argus depends on, see CSI camera driver on Jetson: V4L2, Argus, and IMX sensor bring-up. If you need to write a custom V4L2 driver for a sensor that isn’t supported out of the box, see how to write a custom V4L2 camera driver for Jetson Orin. If you need camera driver development or ISP bring-up beyond what your sensor vendor provides, ProventusNova handles Jetson camera driver development.
FAQ
What is the NVIDIA Argus API and how is it different from V4L2?
Argus (libargus) is NVIDIA’s proprietary camera stack that sits above the V4L2 kernel driver. V4L2 gives you raw frame access — Bayer or YUV — with no ISP processing. Argus adds auto-exposure, auto-white-balance, HDR, and noise reduction through the Jetson ISP hardware. Both require the same kernel driver underneath; the choice between them is made at the application layer.
How do I start nvargus-daemon on Jetson?
Run sudo systemctl start nvargus-daemon to start it once, or sudo systemctl enable nvargus-daemon to start it automatically at boot. Verify it’s running with systemctl status nvargus-daemon. If the daemon isn’t running, nvarguscamerasrc will produce “No cameras available” and LibArgus calls will fail immediately.
Why does nvarguscamerasrc say “No cameras available”?
Three causes cover almost all cases: (1) nvargus-daemon isn’t running; (2) the sensor kernel driver failed to probe — check dmesg | grep -i camera for probe errors; (3) the sensor isn’t registered in the Argus sensor registry — the kernel driver must implement the tegracam interface for Argus to recognize it.
Can I use Argus without a display server running?
Yes. nvargus-daemon runs as a system service and doesn’t require X or Wayland. GStreamer pipelines using nvarguscamerasrc work fully headless — pipe to a file, UDP stream, or inference pipeline without any display.
When should I use Argus instead of V4L2 directly?
Use Argus (nvarguscamerasrc or LibArgus) when you need ISP processing: auto-exposure, auto-white-balance, HDR, or denoise. Use V4L2 directly when you need raw Bayer frames, precise control over every ISP parameter, or compatibility with non-NVIDIA tooling.
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
What is the NVIDIA Argus API and how is it different from V4L2?
Argus (libargus) is NVIDIA's proprietary camera stack that sits above the V4L2 kernel driver. V4L2 gives you raw frame access — Bayer or YUV — with no ISP processing. Argus adds auto-exposure, auto-white-balance, HDR, and noise reduction through the Jetson ISP hardware. Both require the same kernel driver underneath; the choice between them is made at the application layer.
How do I start nvargus-daemon on Jetson?
Run 'sudo systemctl start nvargus-daemon' to start it once, or 'sudo systemctl enable nvargus-daemon' to start it automatically at boot. Verify it's running with 'systemctl status nvargus-daemon'. If the daemon isn't running, nvarguscamerasrc will produce 'No cameras available' and LibArgus calls will fail immediately.
Why does nvarguscamerasrc say 'No cameras available'?
Three causes cover almost all cases: (1) nvargus-daemon isn't running — start it with 'sudo systemctl start nvargus-daemon'; (2) the sensor kernel driver failed to probe — check 'dmesg | grep -i camera' for probe errors; (3) the sensor isn't registered in the Argus sensor registry — the kernel driver must implement the tegracam interface for Argus to recognize it.
Can I use Argus without a display server running?
Yes. nvargus-daemon runs as a system service and doesn't require X or Wayland. GStreamer pipelines using nvarguscamerasrc work fully headless — pipe to a file, UDP stream, or inference pipeline without any display. The daemon handles the ISP entirely in the background.
When should I use Argus instead of V4L2 directly?
Use Argus (nvarguscamerasrc or LibArgus) when you need ISP processing: auto-exposure, auto-white-balance, HDR, or denoise. Use V4L2 directly when you need raw Bayer frames, precise control over every ISP parameter, or compatibility with non-NVIDIA tooling. For most production Jetson deployments with standard cameras, Argus is the right default.
Written by
Andrés CamposCo-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