nvdrmvideosink and gdkpixbufoverlay on Jetson: Working Pipeline
jetsongstreamernvdrmvideosinkgdkpixbufoverlaynvmmoverlay

nvdrmvideosink and gdkpixbufoverlay on Jetson: Working Pipeline

Andres Campos ·

If you are building a GStreamer pipeline on Jetson that needs to render video to a display without a running compositor, and you want to overlay PNG or JPEG graphics on top of the camera feed, the combination of nvdrmvideosink and gdkpixbufoverlay comes up quickly. The problem is that they have an incompatible memory format between them — gdkpixbufoverlay produces system RAM buffers, and nvdrmvideosink expects NVMM. The fix is a second nvvidconv stage, but getting the caps chain right takes some trial and error.

Key Insights

  • nvdrmvideosink renders directly via DRM/KMS — the right choice for headless or kiosk setups with no Wayland compositor
  • gdkpixbufoverlay works with system RAM buffers; you must convert back to NVMM with nvvidconv before nvdrmvideosink
  • The full pipeline requires two nvvidconv stages: one before the overlay (NVMM to system RAM) and one after (system RAM back to NVMM)
  • For overlays that need to stay entirely in NVMM memory, nvdsosd (NVIDIA DeepStream OSD) is the alternative — but it requires the DeepStream SDK and uses a different metadata-based API
  • The supported input format for nvdrmvideosink is video/x-raw(memory:NVMM),format=NV12 — other formats may require an additional nvvidconv conversion step

Understanding the memory incompatibility

nvarguscamerasrc outputs video/x-raw(memory:NVMM),format=NV12. That is GPU-mapped memory — fast, zero CPU copies, stays in hardware. gdkpixbufoverlay is a standard GStreamer element from the gst-plugins-good package. It reads your overlay image file, composites it onto each video buffer, and outputs video/x-raw (system RAM). nvdrmvideosink then expects video/x-raw(memory:NVMM) again.

So the memory path is:

NVMM (camera) → system RAM (gdkpixbufoverlay) → NVMM (nvdrmvideosink)

Both conversions happen via nvvidconv. The element handles both directions.

Working pipeline

gst-launch-1.0 \
  nvarguscamerasrc sensor-id=0 ! \
  video/x-raw(memory:NVMM),width=1920,height=1080,format=NV12,framerate=30/1 ! \
  nvvidconv ! \
  video/x-raw,format=BGRx ! \
  gdkpixbufoverlay location=/path/to/logo.png \
    offset-x=20 offset-y=20 \
    overlay-width=200 overlay-height=100 ! \
  nvvidconv ! \
  video/x-raw(memory:NVMM),format=NV12 ! \
  nvdrmvideosink sync=false

The explicit caps after each nvvidconv are important. Without them, GStreamer may pick a format path that causes a second negotiation failure downstream.

For a live camera feed where you want to minimize latency, add a leaky queue before the display:

gst-launch-1.0 \
  nvarguscamerasrc sensor-id=0 ! \
  video/x-raw(memory:NVMM),width=1920,height=1080,format=NV12,framerate=30/1 ! \
  nvvidconv ! \
  video/x-raw,format=BGRx ! \
  gdkpixbufoverlay location=/path/to/logo.png offset-x=20 offset-y=20 \
    overlay-width=200 overlay-height=100 ! \
  nvvidconv ! \
  video/x-raw(memory:NVMM),format=NV12 ! \
  queue max-size-buffers=1 leaky=2 ! \
  nvdrmvideosink sync=false

gdkpixbufoverlay properties

PropertyTypeDescription
locationstringPath to PNG, JPEG, or any GdkPixbuf-supported image
offset-xintHorizontal position in pixels from left edge
offset-yintVertical position in pixels from top edge
overlay-widthintScale overlay to this width (0 = original size)
overlay-heightintScale overlay to this height (0 = original size)
alphafloatOverlay opacity, 0.0 to 1.0
relative-xfloatPosition as fraction of frame width (0.0 to 1.0)
relative-yfloatPosition as fraction of frame height (0.0 to 1.0)

To update the overlay image at runtime, set the location property on the element while the pipeline is running:

overlay = pipeline.get_by_name("overlay")
overlay.set_property("location", "/path/to/new-logo.png")

Which display sink to use

The three common display sinks on Jetson have different requirements:

SinkCompositor neededInput formatUse case
nvdrmvideosinkNovideo/x-raw(memory:NVMM)Headless, kiosk, no desktop
nv3dsinkYes (Weston/Wayland)video/x-raw(memory:NVMM)Wayland desktop
waylandsinkYes (any Wayland)video/x-rawStandard Wayland

If you are running under a full desktop environment (GNOME on JetPack 4.x, or Weston on JetPack 5/6), use nv3dsink instead. nvdrmvideosink requires exclusive access to the DRM device and will conflict with a running compositor.

Common errors

nvdrmvideosink: DRM device not found — Check ls /dev/dri/. The display driver must be loaded. If the device exists but the error persists, another process (a compositor) may have exclusive access.

Negotiation failed between nvvidconv and nvdrmvideosink — Add explicit caps after the second nvvidconv: video/x-raw(memory:NVMM),format=NV12. Without explicit caps, GStreamer may select a format that nvdrmvideosink does not accept.

gdkpixbufoverlay: Failed to load — Verify the image path is correct and the image is a supported format. gdkpixbufoverlay requires gst-plugins-good with GdkPixbuf support compiled in; verify with gst-inspect-1.0 gdkpixbufoverlay.

For lower-latency overlay that stays entirely in NVMM, consider NVIDIA’s nvdsosd element from DeepStream — it draws text and rectangle overlays in GPU memory without the CPU round-trip.

Frequently Asked Questions

What is nvdrmvideosink and when should I use it on Jetson?

nvdrmvideosink renders video directly via DRM/KMS without a compositor. Use it in headless or kiosk setups where Wayland is not running. Use nv3dsink or waylandsink when a compositor is present.

Why does nvdrmvideosink require video/x-raw(memory:NVMM)?

It reads directly from GPU-mapped DMA memory to compose the display output without a CPU copy. System RAM buffers are not accepted — use nvvidconv to convert before the sink.

Can I use gdkpixbufoverlay directly before nvdrmvideosink?

No. gdkpixbufoverlay outputs system RAM buffers. You need an nvvidconv stage after it to convert back to NVMM before nvdrmvideosink.

What is the difference between nvdrmvideosink, nv3dsink, and waylandsink on Jetson?

nvdrmvideosink is DRM/KMS direct, no compositor needed. nv3dsink is OpenGL-based, requires Wayland/Weston. waylandsink is standard Wayland protocol. For embedded headless use, nvdrmvideosink is the right choice.

nvdrmvideosink says ‘DRM device not found’ — how do I fix this?

Check ls /dev/dri/. The NVIDIA display driver must be loaded, and no compositor should have exclusive access to the DRM device.


ProventusNova builds production GStreamer pipelines on Jetson for hardware startups. Talk to us about your embedded video pipeline.

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 nvdrmvideosink and when should I use it on Jetson?

nvdrmvideosink is a GStreamer sink that renders video directly to the display using DRM/KMS, bypassing any compositor. Use it in headless or embedded setups where there is no Wayland compositor running — it renders directly to the framebuffer. Use nv3dsink or waylandsink instead when running under Weston/GNOME.

Why does nvdrmvideosink require video/x-raw(memory:NVMM)?

nvdrmvideosink expects input in NVMM (GPU-mapped DMA memory). It reads directly from that memory space to compose the display output without a CPU copy. If you pass system RAM buffers without converting to NVMM first via nvvidconv, caps negotiation will fail.

Can I use gdkpixbufoverlay directly before nvdrmvideosink?

Not directly. gdkpixbufoverlay outputs system RAM buffers (video/x-raw), but nvdrmvideosink needs NVMM. You must add an nvvidconv stage after gdkpixbufoverlay to convert back to NVMM before the sink.

What is the difference between nvdrmvideosink, nv3dsink, and waylandsink on Jetson?

nvdrmvideosink: DRM/KMS direct rendering, no compositor needed. nv3dsink: OpenGL-based, requires a running Wayland/Weston compositor. waylandsink: standard Wayland protocol, requires a compositor. For embedded or headless use without a desktop environment, nvdrmvideosink is the right choice.

nvdrmvideosink says 'DRM device not found' — how do I fix this?

This error means no DRM device is available at /dev/dri/card0 or /dev/dri/cardX. Check that the display is connected (or that DRM is initialized without a physical display), and verify with 'ls /dev/dri/'. On Jetson, the DRM device requires the NVIDIA display driver to be loaded.

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