ST 2110 Source Operator#
Authors: Oliver Cleveley-Jones (XRlabs)
Supported platforms: x86_64, aarch64
Language: C++, Python
Last modified: March 10, 2026
Latest version: 1.0.0
Minimum Holoscan SDK version: 3.7.0
Tested Holoscan SDK versions: 3.7.0, 3.10.0, 3.11.0
Contribution metric: Level 2 - Trusted

The ST 2110 Source operator receives SMPTE ST 2110-20 uncompressed video streams over IP networks. This operator is designed for professional broadcast and media production workflows requiring video ingestion from ST 2110-compliant sources.
Overview#
SMPTE ST 2110 is a suite of standards for the transmission of professional media over managed IP networks. ST 2110-20 specifically defines the transport of uncompressed video using RTP (Real-time Transport Protocol). This operator:
- Receives ST 2110-20 RTP packets via Linux UDP sockets
- Parses RTP and ST 2110-20 headers for frame reassembly
- Reassembles packets into complete video frames using line number/offset addressing
- Provides CUDA kernels for 10-bit YCbCr to RGBA/NV12 conversion
- Supports multiple simultaneous output formats
- Compatible with both x86_64 and aarch64 (ARM64) platforms including NVIDIA Thor AGX
Architecture#
The operator uses a triple-buffer architecture with CUDA pinned memory for efficient CPU-to-GPU transfer:
UDP Socket (multicast)
│
▼
recvmmsg() batch receive
│
▼
RTP/ST2110 header parsing
│
▼
Triple-buffer (pinned memory)
[Assembling] [Complete] [Complete]
│
▼
cudaMemcpyAsync (H2D)
│
├──► raw_output (YCbCr-4:2:2-10bit)
│
├──► CUDA kernel ──► rgba_output (RGBA 8-bit)
│
└──► CUDA kernel ──► nv12_output (NV12 8-bit)
Output Ports#
The operator provides three output ports:
| Port | Format | Description |
|---|---|---|
raw_output |
YCbCr-4:2:2-10bit | Raw ST 2110-20 frame data (always emitted) |
rgba_output |
RGBA 8-bit | Converted frame for visualization (optional) |
nv12_output |
NV12 8-bit | Converted frame for video encoding (optional) |
Parameters#
| Parameter | Type | Description | Default |
|---|---|---|---|
multicast_address |
string | Multicast IP address for ST 2110 stream | "239.0.0.1" |
port |
uint16_t | UDP port for ST 2110 stream | 5004 |
interface_name |
string | Linux network interface name (e.g., "mgbe0_0", "eth0") | "eth0" |
width |
uint32_t | Width of the video stream in pixels | 1920 |
height |
uint32_t | Height of the video stream in pixels | 1080 |
framerate |
uint32_t | Expected frame rate of the video stream | 60 |
stream_format |
string | Input format: "YCbCr-4:2:2-10bit", "YCbCr-4:2:2-8bit", "RGBA-8bit" | "YCbCr-4:2:2-10bit" |
enable_rgba_output |
bool | Enable RGBA conversion and emission | false |
enable_nv12_output |
bool | Enable NV12 conversion and emission | false |
batch_size |
uint32_t | Number of packets to receive per compute() call | 1000 |
max_packet_size |
uint16_t | Maximum ST 2110 packet size in bytes | 1514 |
Requirements#
Hardware#
- CUDA-capable NVIDIA GPU
- Network interface with multicast support
- ST 2110-compliant video source (e.g., Blackmagic Design equipment)
Software#
- Holoscan SDK 3.7.0 or later
- CUDA Toolkit 12.x or later
- Linux with multicast routing configured
Usage Examples#
Python Example#
from holoscan.core import Application
from holoscan.operators import HolovizOp
from holohub.st2110_source import ST2110SourceOp
class ST2110App(Application):
def compose(self):
# Create ST 2110 source operator with RGBA output enabled
source = ST2110SourceOp(
self,
name="st2110_source",
multicast_address="239.255.66.60",
port=16388,
interface_name="mgbe0_0",
width=1920,
height=1080,
framerate=50,
stream_format="YCbCr-4:2:2-10bit",
enable_rgba_output=True
)
# Visualize received video
visualizer = HolovizOp(
self,
name="visualizer",
width=1920,
height=1080
)
# Connect RGBA output to visualizer
self.add_flow(source, visualizer, {("rgba_output", "receivers")})
if __name__ == "__main__":
app = ST2110App()
app.run()
C++ Example#
#include "holoscan/holoscan.hpp"
#include "st2110_source.hpp"
class ST2110App : public holoscan::Application {
public:
void compose() override {
using namespace holoscan;
auto source = make_operator<ops::ST2110SourceOp>(
"st2110_source",
Arg("multicast_address", "239.255.66.60"),
Arg("port", static_cast<uint16_t>(16388)),
Arg("interface_name", "mgbe0_0"),
Arg("width", 1920u),
Arg("height", 1080u),
Arg("framerate", 50u),
Arg("stream_format", "YCbCr-4:2:2-10bit"),
Arg("enable_rgba_output", true));
auto visualizer = make_operator<ops::HolovizOp>(
"visualizer",
Arg("width", 1920),
Arg("height", 1080));
add_flow(source, visualizer, ('rgba_output', 'receivers'));
}
};
int main() {
auto app = holoscan::make_application<ST2110App>();
app->run();
return 0;
}
Building#
To build the operator:
./holohub build st2110_source
To build with Python bindings:
./holohub build st2110_source --configure-args "-DHOLOHUB_BUILD_PYTHON=ON"
Network Configuration#
System Configuration#
Increase the socket buffer size for high-bandwidth streams:
# Temporary (until reboot)
sudo sysctl -w net.core.rmem_max=268435456
sudo sysctl -w net.core.rmem_default=268435456
# Permanent (add to /etc/sysctl.conf)
net.core.rmem_max=268435456
net.core.rmem_default=268435456
Multicast Routing#
Ensure multicast traffic is routed to the correct interface:
# Add multicast route for your interface
sudo ip route add 239.0.0.0/8 dev mgbe0_0
# Verify multicast group membership
ip maddr show dev mgbe0_0
Supported Video Formats#
The operator supports ST 2110-20 uncompressed video at various resolutions:
- 720p (1280x720)
- 1080p/1080i (1920x1080)
- 2K (2048x1080)
- UHD/4K (3840x2160, 4096x2160)
Supported input formats:
- YCbCr-4:2:2-10bit: 2.5 bytes per pixel (default, common for broadcast)
- YCbCr-4:2:2-8bit: 2 bytes per pixel
- RGBA-8bit: 4 bytes per pixel
Troubleshooting#
No packets received#
- Verify multicast address and port match your ST 2110 source
- Check interface name is correct (
ip link show) - Ensure multicast routing is configured
- Check firewall allows UDP traffic:
sudo ufw allow 5004/udp
Packet drops / frame tearing#
- Increase socket buffer size (see Network Configuration)
- Reduce other network traffic on the interface
- Check CPU load - ensure sufficient cores available
Color issues#
- Verify
stream_formatmatches your source (10-bit vs 8-bit) - Check source colorimetry settings (BT.709 assumed)
Platform Support#
- x86_64: Full support
- aarch64 (ARM64): Full support including NVIDIA Thor AGX with MGBE
References#
- SMPTE ST 2110-20:2017 - Uncompressed Video
- SMPTE ST 2110-21:2017 - Traffic Shaping and Delivery Timing
- Holoscan SDK Documentation
API Reference#
Python#
ST2110SourceOp#
Constructor Parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
fragment |
Fragment |
Required | The fragment that the operator belongs to. |
multicast_address |
str |
Optional | Multicast IP address for ST 2110 stream (e.g., "239.255.66.60"). Default value is "239.0.0.1". |
port |
int |
Optional | UDP port for ST 2110 stream. Default value is 5004. |
interface_name |
str |
Optional | Linux network interface name (e.g., "mgbe0_0", "eth0"). Default value is "eth0". |
width |
int |
Optional | Width of the video stream in pixels. Default value is 1920. |
height |
int |
Optional | Height of the video stream in pixels. Default value is 1080. |
framerate |
int |
Optional | Expected frame rate of the video stream. Default value is 60. |
stream_format |
str |
Optional | Input stream format. Supported: "YCbCr-4:2:2-10bit", "YCbCr-4:2:2-8bit", "RGBA-8bit". Default value is "YCbCr-4:2:2-10bit". |
enable_rgba_output |
bool |
Optional | Enable RGBA conversion and emission on rgba_output port. Default value is False. |
enable_nv12_output |
bool |
Optional | Enable NV12 conversion and emission on nv12_output port. Default value is False. |
batch_size |
int |
Optional | Number of packets to receive per compute() call. Default value is 1000. |
max_packet_size |
int |
Optional | Maximum size of ST 2110 packets in bytes. Default value is 1514. |
rtp_header_size |
int |
Optional | Size of RTP header in bytes. Default value is 12. |
name |
str |
Optional | The name of the operator. Default value is "st2110_source". |