Skip to content

About

This repository contains the Direct View LED Software Toolkit — an open-source transmitter & receiver application developed by Intel as part of the Open Visual Cloud initiative. It is designed for professional AV-over-IP installations that drive direct-view LED video walls using the SMPTE ST 2110 suite of standards.

Topics

Resources

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

75 Commits

Folders and files

Repository files navigation

Direct View LED Software Toolkit

License CI Coverity Scan Build Status Ubuntu MTL OpenSSF Scorecard

Table of Contents

Overview

The Direct View LED Software Toolkit drives direct-view LED walls with uncompressed video over IP using SMPTE ST 2110-20. It is built on FFmpeg and the Media Transport Library (MTL) and contains two applications:

Application Role Details
dvledtx Transmitter. Decodes a video file (or captures an X11 screen), optionally scales it, splits it into crop regions and sends each region as an independent ST 2110-20 stream. dvledtx/README.md
dvledrx Receiver. Receives one or more ST 2110-20 streams and renders them on X11 displays — one window, a composite of all streams, or one window per physical output (HDMI/DP). dvledrx/README.md

Use case — LED video walls: drive multiple LED panels from a single source, with each panel (or LED controller) receiving its own cropped portion of the frame.

Architecture

Direct View LED Software Toolkit architecture: dvledtx transmitter and dvledrx receiver stacks

System Requirements

Component Requirement
OS Ubuntu 22.04 LTS and Ubuntu 24.04 LTS
CPU Intel 12th Gen Core processors or above, including Intel Core Ultra Series 3
NIC Intel Ethernet Controller I225 or above (I225, I226, E610 and E810 series)
Memory Hugepages configured (typically 2 GB+)
Kernel IOMMU and VFIO support enabled
Display (RX only) An X11 (Xorg) session; Wayland is not supported

Deployment Security Model

dvledtx and dvledrx follow a layered security model. The applications validate and bound their inputs — including configuration parsing, log file destinations, decoder behaviour and resource limits — and are covered by static analysis, AFL/libFuzzer fuzzing and dependency CVE tracking in CI. Transport-level security is a separate layer: SMPTE ST 2110-20 and the PTP timing it depends on do not define authentication, encryption or integrity protection, which is a property of the standards common to all ST 2110 equipment. The deployment architecture supplies that layer.

We recommend that all hosts in a deployment are air-gapped. The TX host, a dedicated L2 switch and the receivers sit inside a locked cabinet with no network path to any other network and no in-band administrative access — no SSH, no management NIC, no remote console, BMC disabled — with administration by physical KVM inside the cabinet. Because "isolated" and "restricted" are used loosely, note that a VLAN on a shared switch, a firewall or a jump host does not meet this definition.

We also recommend hardening the dedicated switch, since its configuration carries the boundary: disable and blackhole every unused port, enable port security (802.1X or sticky MAC) with a shutdown violation action, disable dynamic trunking, and enable IGMP snooping, storm control, BPDU guard and DHCP snooping.

See Deployment Assumptions and Security Model for the trust boundary, deployment assumptions, switch hardening recommendations, controlled ingress of configuration and video content, the controls the toolkit implements, the residual risk, and a commissioning validation checklist.

Documentation Map

Topic Document
Common installation (TX and RX) Common Installation: MTL and DPDK
TX dependencies: screen capture, VA-API, FFmpeg with the MTL plugin Dependencies for dvledtx (TX)
RX dependencies Dependencies for dvledrx (RX)
Verify the installation Verify the Installation
Build both applications Build
Host setup (TX and RX) Host Setup
Run (TX and RX) Run
Transmitter: JSON configuration, formats, scaling, PTP, VA-API decode, screen capture, logging dvledtx/README.md
Receiver: JSON configuration, display modes, multi-monitor walls, PTP, logging dvledrx/README.md
Deployment assumptions and security model docs/assumptions.md
Reporting security issues Security.md

Notices

FFmpeg

FFmpeg is an open source project licensed under LGPL and GPL. See https://www.ffmpeg.org/legal.html. You are solely responsible for determining if your use of FFmpeg requires any additional licenses. Intel is not responsible for obtaining any such licenses, nor liable for any licensing fees due, in connection with your use of FFmpeg.

Common Installation: MTL and DPDK

Both applications are built on the Media Transport Library (MTL) and DPDK. Install them on every TX and RX host by following MTL's own guides at the pinned commit.

Dependency Version Source
Media Transport Library MTL 26.01+, commit 7bee2423 (26.01.0.DEV) MTL build guide
DPDK 26.03 (DPDK_VER) with the MTL patches versions.env at the pinned commit

These are the versions CI builds against. Supported OS: Ubuntu 22.04 and 24.04 LTS.

Clone MTL at the pinned commit:

git clone https://github.com/OpenVisualCloud/Media-Transport-Library.git
cd Media-Transport-Library
git checkout 7bee24231c864d12da6db2c2ffbfd3986717af5a
export mtl_source_code=${PWD}
cd ..

Then follow the MTL build guide at that commit:

DPDK version: use the DPDK_VER from versions.env (26.03) and the matching ${mtl_source_code}/patches/dpdk/26.03/ patches. The example commands in the guide at this commit still show 25.11.

Dependencies for dvledtx (TX)

dvledtx decodes and transmits through FFmpeg with the MTL plugin. Install the packages below before building FFmpeg: FFmpeg's ./configure only enables optional features whose packages are already installed.

Screen Capture Packages

Needed for input_mode: screen_capture. FFmpeg's x11grab device is only compiled in when these packages are present.

sudo apt-get install -y libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev

VA-API Hardware Decode Packages (Optional)

Needed only for "hwaccel": true. Also add --enable-vaapi to FFmpeg's ./configure line.

sudo apt-get install -y libva-dev vainfo intel-media-va-driver-non-free

FFmpeg with the MTL Plugin

Follow the MTL FFmpeg plugin build guide at the pinned commit. It builds FFmpeg 7.0 (FFMPEG_VERSION in versions.env).

  • 12-bit formats (yuv422p12le, yuv444p12le, gbrp12le) need MTL and FFmpeg built from the same pinned commit. The plugin sources are compiled into FFmpeg's libavdevice, so rebuilding MTL alone is not enough.
  • Up to 8 NICs on the default dvledtx FFmpeg TX path rely on the p2_port..p7_port AVOptions present in the plugin at the pinned commit.
Packages Used for
libxcb1-dev, libxcb-shm0-dev, libxcb-xfixes0-dev FFmpeg x11grab, for input_mode: screen_capture
libva-dev, vainfo, intel-media-va-driver-non-free (optional) VA-API hardware decode, for "hwaccel": true
FFmpeg 7.0 with the MTL plugin Decoding, scaling and ST 2110-20 transmission

Dependencies for dvledrx (RX)

dvledrx receives directly through MTL and renders with X11; it does not use FFmpeg.

sudo apt-get install -y libx11-dev libxext-dev libxrandr-dev zlib1g-dev
Packages Used for
libx11-dev, libxext-dev, libxrandr-dev X11 rendering, MIT-SHM and XRandR output placement
zlib1g-dev Log file compression

dvledrx also uses libjson-c-dev, which is already installed with the MTL prerequisites.

Note: scripts/build.sh builds both applications from one Meson project, which checks for the FFmpeg libraries. To build on an RX-only host, FFmpeg must still be installed. The MTL plugin and the optional TX packages are not needed.

Verify the Installation

# Common: MTL and DPDK
pkg-config --modversion libdpdk          # expected: 26.03.x
pkg-config --modversion mtl              # expected: 26.01.0.DEV
ls /usr/local/include/mtl/mtl_api.h      # MTL headers present
ldconfig -p | grep libmtl                # libmtl.so => /usr/local/lib/x86_64-linux-gnu/libmtl.so

# dvledtx: FFmpeg with the MTL plugin
pkg-config --modversion libavformat      # FFmpeg 7.0 (libavformat 61.x)
ffmpeg -hide_banner -muxers  | grep mtl_st20p   # MTL plugin present
ffmpeg -hide_banner -devices | grep x11grab     # screen capture
ffmpeg -hide_banner -hwaccels | grep vaapi      # optional: hardware decode

# dvledrx: X11 libraries
pkg-config --modversion x11 xext xrandr

Build

With the dependencies installed, clone the repository and build both applications:

git clone https://github.com/OpenVisualCloud/directview-led-software-toolkit
cd directview-led-software-toolkit
bash scripts/build.sh

The script wipes and recreates build/, then produces:

Binary Path
Transmitter build/dvledtx/dvledtx
Receiver build/dvledrx/dvledrx

Extra Meson options are passed straight through. The only project option selects the dvledtx TX path (it does not affect dvledrx):

Option Default Description
enable_mtl_tx false false: transmit through FFmpeg's mtl_st20p muxer. true: transmit with MTL's pipeline API (st20p_tx_*) directly.
bash scripts/build.sh -Denable_mtl_tx=true

Manual equivalent:

meson setup build [-Denable_mtl_tx=true]
ninja -C build

Host Setup

These steps are required on both the TX and RX hosts. They only need to be done once (hugepages and NIC binding must be repeated after each reboot unless made persistent).

IOMMU / VFIO Kernel Parameters (GRUB)

MTL requires IOMMU and VFIO. Ensure these parameters are present in GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub:

intel_iommu=on iommu=pt pcie_aspm=off pcie_port_pm=off vfio-pci.disable_idle_d3=1

For example:

sudo nano /etc/default/grub
# GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on iommu=pt pcie_aspm=off pcie_port_pm=off vfio-pci.disable_idle_d3=1"
sudo update-grub
sudo reboot

Verify after reboot:

cat /proc/cmdline | grep intel_iommu
dmesg | grep -i iommu    # should show "DMAR: IOMMU enabled"

VFIO Group Setup

MTL accesses the NIC through VFIO; the user running the applications must belong to the vfio group:

sudo groupadd vfio            # if it does not already exist
sudo usermod -aG vfio $USER
newgrp vfio                   # or log out and back in
id -nG $USER                  # verify

Bind NICs to DPDK and Configure Hugepages

Follow the MTL run guide for the pinned commit:

Quick reference:

# Find the NIC PCI address (use the BDF form "0000:06:00.0" in the JSON configs)
lspci | grep Ethernet

# Either bind a PF to vfio-pci (TX or RX)
sudo ${mtl_source_code}/script/nicctl.sh bind_pmd 0000:06:00.0

# Or use VFs:
#   TX host: plain VFs are enough
sudo ${mtl_source_code}/script/nicctl.sh create_vf 0000:06:00.0
#   RX host: trusted VFs plus a promiscuous PF (see dvledrx/README.md, Virtual Functions)
sudo ${mtl_source_code}/script/nicctl.sh create_tvf 0000:06:00.0 <num_vfs>
sudo ip link set <pf_iface> promisc on

dpdk-devbind.py --status       # target NIC/VFs should show drv=vfio-pci

# Allocate hugepages
sudo sysctl -w vm.nr_hugepages=2048
grep Huge /proc/meminfo

VF settings, PF promiscuous mode and hugepages are lost at reboot. Re-apply them at every boot, for example from a startup script or systemd unit. For RX VF details see dvledrx — Virtual Functions.

Locked-Memory Limit (Non-Root Run)

The applications run as a normal user, so DPDK needs a high enough locked-memory limit (RLIMIT_MEMLOCK). If it is too low, start-up fails with:

EAL: Cannot set up DMA remapping, error 12 (Cannot allocate memory)

Raise the limit as described in the MTL run guide: notes for non-root run, for example by adding these lines to /etc/security/limits.conf and rebooting:

<user>    hard   memlock           unlimited
<user>    soft   memlock           unlimited

Check with ulimit -l; it should print unlimited.

Run

Both applications are configured entirely from a JSON file and share the same command line. Before running, make sure the host setup is complete and edit the sample config so interfaces[].name matches your NIC PCI address and the IP addresses match your network.

Command-Line Options

Option Description
-C, --config <file> JSON configuration file (required)
-t, --test-time <secs> Run for N seconds (1..86400), then exit cleanly
-v, --version Show the version and exit
--help Show usage

Run the Transmitter (dvledtx)

./build/dvledtx/dvledtx --config dvledtx/config/tx_fullhd_single_session.json

Set video.tx_url in the config to your source video file (or use input_mode: screen_capture). Configuration reference: dvledtx/README.md — JSON Configuration.

Run the Receiver (dvledrx)

dvledrx renders through X11, so it needs a running Xorg session and DISPLAY set:

export DISPLAY=:0
./build/dvledrx/dvledrx --config dvledrx/config/rx_fullhd_1session.json

Configuration reference: dvledrx/README.md — JSON Configuration.

End-to-End Example

A TX session and the RX session that receives it must agree on:

Must match TX config RX config
Multicast group interfaces[].dip interfaces[].dip
UDP port tx_sessions[].udp_port rx_sessions[].udp_port
RTP payload type tx_sessions[].payload_type rx_sessions[].payload_type
Pixel format tx_video.fmt video.fmt
Frame rate tx_video.fps video.fps
Stream size tx_sessions[].crop.w × crop.h rx_sessions[].crop.w × crop.h

For example, a Full HD frame split into three 640×1080 strips:

# TX host
./build/dvledtx/dvledtx --config dvledtx/config/tx_fullhd_multi_session.json

# RX host (composite window of the three strips)
export DISPLAY=:0
./build/dvledrx/dvledrx --config dvledrx/config/rx_crop_3sessions.json

The shipped samples are independent examples: before pairing them, align the multicast dip and fmt values (here tx_fullhd_multi_session.json uses 239.168.85.21 / yuv422p10le and rx_crop_3sessions.json uses 239.168.85.20 / gbrp12le).

Stopping the Applications

Press Ctrl+C (or send SIGTERM) for a clean shutdown; --test-time stops automatically. Closing a dvledrx window also stops the receiver. If an application becomes unresponsive:

pkill -9 -f dvledtx
pkill -9 -f dvledrx

Running Unit Tests

sudo apt install -y libcmocka-dev xvfb xauth
pip install gcovr

bash scripts/test.sh                # TX + RX unit tests with a coverage report
bash scripts/test.sh --no-coverage  # tests only

The script builds into build-tests/ and runs every test with meson test. dvledrx X11/session tests run under xvfb-run. dvledtx screen-capture success tests run only when a live X display is detected (or DVLED_TEST_DISPLAY is set to an x11grab source such as :99.0+0,0).

Troubleshooting

Application-specific issues are covered in dvledtx/README.md and dvledrx/README.md. Common issues:

  1. MTL initialization failed

    • Check that the PCI address in the config matches your hardware:
      lspci | grep Ethernet
      # Example output: 06:00.0 Ethernet controller: Intel Corporation ...
      # Use BDF format in config: "0000:06:00.0"
    • Check MTL, DPDK and FFmpeg are installed at the expected versions — see Verify the Installation.
    • Verify the NIC is bound to VFIO:
      sudo ${mtl_source_code}/script/nicctl.sh list all
      # Or use dpdk-devbind.py:
      dpdk-devbind.py --status
      # The target NIC should show "drv=vfio-pci"
    • Ensure IOMMU is enabled — see IOMMU / VFIO Kernel Parameters.
    • Verify the network card is supported (Intel I225, I226, E610, E810 series).
  2. Hugepage allocation failure / transmission issues

    grep Huge /proc/meminfo                  # HugePages_Free should be > 0
    sudo sysctl -w vm.nr_hugepages=2048      # make persistent in /etc/sysctl.conf

    Also check the NIC has enough bandwidth (uncompressed 1080p30 4:2:2 10-bit ≈ 1.3 Gb/s per stream, more for 4:4:4 / 12-bit).

  3. Permission denied (VFIO)

    • Ensure the user is in the vfio group — see VFIO Group Setup.
    • Check ls -la /dev/vfio/ — group should be vfio with rw permissions.
  4. pip install fails with externally-managed-environment (Ubuntu 24.04, PEP 668)

    • See the note in the MTL build guide, or install with pip install --break-system-packages <package>.
  5. FFmpeg ./configure fails with nasm/yasm not found or too old

    sudo apt install -y nasm

    Then re-run ./configure.

  6. Build fails with Dependency "mtl" not found or missing libav*

    • Make sure /usr/local is on the pkg-config path:
      export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH

Contributing

Contributions are welcome. Please open an issue or submit a pull request on GitHub.

License

This project is licensed under the BSD 3-Clause License. See LICENSE for details.

About

This repository contains the Direct View LED Software Toolkit — an open-source transmitter & receiver application developed by Intel as part of the Open Visual Cloud initiative. It is designed for professional AV-over-IP installations that drive direct-view LED video walls using the SMPTE ST 2110 suite of standards.

Topics

Resources

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages