Video I/O Vendor Implementation Guide
Video I/O Vendor Implementation Guide
This guide describes how capture-card vendors subclass the Holoscan SDK
VideoAcquisitionOperator and VideoTransmissionOperator to provide
SDK-native multi-stream video capture and playout.
Architecture Overview
The base class handles:
The vendor subclass provides:
Step 1: Subclass the Base Operator
Acquisition (Capture)
Transmission (Playout)
Step 2: Implement setup() — Register Vendor Parameters
Call the base setup() first. This registers all common parameters (uri, width, etc.)
and the correct number of I/O ports based on num_streams(). Then add your vendor-specific
parameters.
For transmission:
Step 3: Implement Lifecycle — start() and stop()
start() is called once after initialize(). Open the device, allocate buffers,
configure the hardware. stop() tears everything down.
Step 4: Implement compute() — The Frame Loop
compute() is called by the scheduler on every tick. For acquisition, dequeue frames from
the hardware and emit them via emit_capture_stream(). For transmission, receive frames via
receive_transmit_stream() and queue them to the hardware.
Acquisition compute()
Transmission compute()
Step 5: Override Capability Reporting (Optional but Recommended)
The default query_capture_capabilities() derives a minimal snapshot from configured
parameters. Override it to query the actual hardware for supported modes, resolutions,
frame rates, and features.
Step 6: Register a Capability Enumerator (Optional)
The registry allows applications to discover available hardware before creating
operator instances. Register an enumerator at library load time (or from a static
initializer) using your vendor backend_id.
Applications can then discover devices without instantiating any operator:
Step 7: Wire Into an Application
Multi-Instance (Preferred — One Operator Per Channel)
The recommended deployment pattern: each operator instance owns one hardware channel. A shared device resource (vendor-specific) ensures safe access to the underlying SDK handle with per-channel reservation.
Multi-Stream (Single Operator, Multiple Ports)
When the vendor SDK manages multiple channels through a single handle and
does not support independent per-channel initialization, use one operator
with num_streams > 1 to expose each channel on a separate output port.
YAML Configuration
Port Naming Convention
Use capture_output_port_name(i) / transmit_input_port_name(i) if you need the
string programmatically. The base caches these in a vector for zero-allocation lookup
in the hot path (emit_capture_stream / receive_transmit_stream).
num_streams vs. channel_indices — When to Use Which
These serve different purposes:
Common patterns:
CMake Integration
Checklist
- Subclass
VideoAcquisitionOperatorand/orVideoTransmissionOperator - Forward all three constructor forms (default,
num_streams,num_streams+ args) - Call base
setup()first in your override, then add vendor parameters - Implement
compute()— useemit_capture_stream()/receive_transmit_stream() - Call
note_acquired_frame()/note_transmitted_frame()on success - Call
note_dropped_frame()on timeout or error - Implement
start()to open device,stop()to close device - Override
query_capture_capabilities()to return real hardware capabilities - Use
backend_id="vendor.<yourname>"for capability reporting - Register a capability enumerator for device discovery (optional)
- Link against
holoscan::ops::video_io - Test with
num_streams= 1 (backward compat) and > 1 (multi-stream) - Validate port naming:
signal,signal_1, …,signal_{N-1}