A Rust-based VLC video output plugin for Blackmagic DeckLink devices, specifically targeting the Intensity Pro 4K.
This plugin enables VLC media player to output video through Blackmagic DeckLink capture/playback cards. It's designed for professional video workflows requiring SDI or HDMI output to external monitors, broadcast equipment, or video routers.
- Primary Target: Blackmagic Design Intensity Pro 4K (PCIe)
- Other DeckLink Cards: Should work with other DeckLink devices that support video output
- Video Output: Send VLC video to DeckLink HDMI/SDI outputs
- Multiple Resolutions: Support for SD, HD, and 4K output modes
- Pixel Formats: UYVY 8-bit, v210 10-bit, ARGB, BGRA
- Scheduled Playback: Frame-accurate video output timing
- Frame Buffering: Configurable buffer pool for smooth playback
- Docker: All builds run inside Docker containers for reproducibility
- Blackmagic DeckLink SDK 15.3: Automatically downloaded during Docker build
- Make: For running build commands
Download the SDK from https://www.blackmagicdesign.com/developer/products/capture-and-playback/sdk-and-software into the root of this repository.
# Install release build (requires root)
make release
# Copy the plugin to /usr/lib/vlc/plugins/video_output/The workspace also builds libgstrsdecklink.so, a GStreamer plugin providing
the rsdecklinkvideosink video sink element (named distinctly from
gst-plugins-bad's stock decklinkvideosink so both can coexist). It accepts
UYVY, BGRA and ARGB at any resolution and scales to the best card mode.
# Build (same `make release`), then install for the current user:
make install-gst-local # ~/.local/share/gstreamer-1.0/plugins/
# or system-wide:
sudo make install-gst # /usr/lib/<arch>/gstreamer-1.0/
# Smoke test inside Docker (no card needed):
make gst-inspect
# Test pattern to the card:
gst-launch-1.0 videotestsrc ! video/x-raw,format=UYVY,width=1920,height=1080,framerate=30/1 ! rsdecklinkvideosink
# As UxPlay's video sink (AirPlay -> DeckLink):
uxplay -vs rsdecklinkvideosinkElement properties: device-index, device-name, mode (auto/1080p60/…),
scaling (nearest/bilinear/bicubic/lanczos/lanczos-gpu), position
(center/fit-width/fit-height/stretch/corners), buffer-count, gpu,
gpu-device, db-path. GPU zero-copy scaling engages with
scaling=lanczos-gpu and BGRA input; everything else uses the CPU scaler.
Video only for now — the decklink crate has no audio output API yet.
A SQLite database is the interface between the GStreamer sink and
decklink-gui, a native desktop control panel. Settings saved in the GUI
override the element properties and are re-applied live — the running
sink notices the change and reopens the output without a pipeline restart
(this is also the only way to configure the sink under uxplay -vs, which
cannot pass element properties). The sink writes status, per-second metrics
(fps, frame time, GPU time), logs, the hardware inventory and — every ~2 s —
preview thumbnails of the incoming frame and the composed frame sent to the
card, back to the same database; the GUI renders them in Settings / Preview /
Devices / Metrics / Logs / Status tabs.
make gui # build the GUI on the host (SDK-free, needs GL/X11 only)
make run-gui # launch it
make scan # inventory the cards + probe supported modes into the DB
# (docker-built binary, runs on the host with the card)The database lives at $DECKLINK_DB or
$XDG_STATE_HOME/decklink/decklink.db (local filesystem required — WAL).
The sink's db-path property overrides it; db-path="" disables the control
plane entirely, restoring pure property-driven behavior. One sink per
database: point concurrent sinks at different db-paths.
The repository is a Cargo workspace with six crates:
crates/decklink— a reusable, VLC-free DeckLink output library: device discovery, display-mode selection, frame pools, scheduled playback, pixel formats, subtitle blending and CPU scaling. GPU scaling (wgpu compute Lanczos + Linux DMA-BUF zero-copy) is behind the optionalgpucargo feature.DeckLinkDisplayis the high-level entry point.crates/vlc-decklink-plugin— the VLC plugin: module descriptor and config helpers (ffi/vlc_module.c), thevout_display_tentry points (plugin.rs) and VLC error mapping. Builds thelibdecklink_plugin.socdylib that VLC loads.crates/gst-decklink-plugin— the GStreamer plugin: aGstVideoSinksubclass (videosink/imp.rs) drivingDeckLinkDisplay, registered asrsdecklinkvideosink. Builds thelibgstrsdecklink.socdylib that GStreamer loads. Itsvideosink/db.rsworker thread connects the sink to the control-plane database.crates/decklink-db— the SQLite control plane: schema, typed API (settings/status/metrics/logs/devices/commands) and the string vocabulary shared by producers and the GUI. SDK-free.crates/decklink-gui— the eframe/egui control panel. Depends only ondecklink-db, so it builds anywhere (make gui).crates/decklink-scan— small CLI that writes the device inventory and mode-support grid into the database without a running pipeline (make scan;--watchservices rescan requests from the GUI).
Other applications can reuse the core library without VLC, e.g.:
[dependencies]
decklink = { git = "https://github.com/simukka/vlc-decklink", features = ["gpu"] }┌─────────────────────────────────────────────────────────────┐
│ VLC Media Player │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ VLC Video Output Plugin API │
│ (vout_display_t) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ crates/vlc-decklink-plugin (VLC glue) │
│ ┌────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ plugin.rs │ │ vlc_module.c │ │ error.rs (codes) │ │
│ │ (entry) │ │ (descriptor) │ │ │ │
│ └────────────┘ └──────────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ crates/decklink (reusable library) │
│ ┌─────────────┐ ┌─────────────────────────────────────┐ │
│ │ display.rs │──│ device.rs │ output.rs │ frame.rs │ │
│ │ (high-level)│ │ blend.rs │ scaling.rs │ gpu/ │ │
│ └─────────────┘ └─────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ FFI Layer (ffi/) │ │
│ │ C wrapper for DeckLink C++ SDK │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Blackmagic DeckLink SDK (C++) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Intensity Pro 4K Hardware │
│ (PCIe 42:00.0) │
└─────────────────────────────────────────────────────────────┘
- Rust Edition: 2021
- DeckLink SDK: 15.3 (Linux)
- VLC API: 3.0 plugin interface
- FFI: bindgen for Rust bindings, C++ wrapper for DeckLink COM API
This project is licensed under the LGPL-2.1-or-later license, compatible with VLC's licensing requirements.
- VLC media player team
- Blackmagic Design for the DeckLink SDK
- The Rust community