Applications, Fragments, and Graphs
🚧 Documentation is under development
The Holoscan SDK guide is currently under active development. Some sections may be incomplete or change without notice.
Questions? Contact RidgeRun or email to support@ridgerun.com.
-
Overview
-
Build, Run, and Validate
-
Core Concepts
-
Operators and Graphs
-
Tensor Data and Memory
-
Interprocess Communication
-
-
Application and Operator Development
- Building an HSDK Application
- Writing a Minimal Operator
- Typed Parameters and Configuration
- Reading, Writing, and Forwarding Data
- Writing Tensor Operators
- Complete Operator Patterns
- Authoring Runtime Behavior
- Runtime Parameter Updates
- Lifecycle Callbacks and Restart Control
- Performance and Debugging
- SDK Source Map
-
Operator Reference
-
Core Operators
-
Holoscan Camera
-
Holoscan RidgeRun
- Overview
- Build and Installation
- ArgusCameraOp
- V4L2SourceOp
- V4L2UserPtrSourceOp
- BgraToPlanarTensorOp
- RawBayerToBgraOp
- RawBayerToYoloTensorOp
- YuyvToBgraOp
- TensorRtInferenceOp
- DrmDisplayOp
- DrmBgraDisplayOp
- X11DisplayOp
- CudaCompositorOp
- DepthColorizerOp
- FakesinkOp
- FrameSkipperOp
- InterprocessSrcOp
- TestPatternOp
-
-
Migration from Holoscan 4.x
-
Examples
-
Core
-
Holoscan Camera
-
Holoscan RidgeRun
-
-
Benchmark and Use Cases
-
Holoscan vs GStreamer
- Overview
-
Capture and Display
-
Capture and Inference
- Compare the workloads
- Implemented Applications
- Framework Selection
- Interprocess
-
Applications, Fragments, and Graphs
Once the intended behavior is clear, rebuild the application from its visible pieces: operators, connections, reusable groups, and process boundaries. The current graph model makes those pieces explicit, so the migration can be checked one connection at a time.
Inventory the existing application
Start by listing the parts of the older application before changing code:
| Existing part | Record before migrating |
|---|---|
| Application | The entry point, configuration source, run command, and completion behavior. |
| Fragment | The operators and connections that belong together, plus the inputs and outputs used by its parent. |
| Operator | Its input and output payloads, parameters, activation rule, and resources. |
| Condition or queue setting | What starts work, which values are paired, and what happens when a value is late or absent. |
| External process | The peer, payload format, transport, startup order, and shutdown behavior. |
This inventory gives the migration a behavior checklist. It also shows which parts belong in the graph and which parts belong in an operator or external endpoint.
Build the new graph
The current Graph owns the application structure. Add an operator with Graph::op(), connect typed ports with Graph::add_flow(), then compile the graph and check the result before running it.
A small graph looks like this:
holoscan::Graph graph{"camera-to-display"};
auto capture = graph.op<CaptureOp>("capture");
auto display = graph.op<DisplayOp>("display");
graph.add_flow(capture->output, display->input);
const auto plan = holoscan::compile(graph);
if (!plan.ok()) {
std::cerr << plan.json() << '\n';
return 1;
}
return holoscan::run(plan);
The graph expresses who is connected to whom. Port types and the page's operator contracts express what can travel across each edge. Queue depth and queue policy belong to the connection when the application needs a bounded buffer or a defined response to pressure. Building Graphs and Queue Policies develops those choices.
A small structural translation
| Older application intent | Current action |
|---|---|
| Group operators for reuse | Create a child Graph with public input and output ports. Bind those ports with export_input() and export_output(), then embed it with embed<ChildGraph>().
|
| Connect named ports | Keep the port names that help diagnostics, but make the connection through typed port members and add_flow().
|
| Treat a reusable fragment as a process | Use an embedded graph for reuse inside one application. Use External Endpoints and Endpoint Catalogs when the peer runs in another process. |
| Start the application after composition | Call compile(), inspect plan.ok(), and then call run().
|
An embedded graph provides reuse and an interface. It does not launch a new operating-system process, and a successful composition does not confirm that devices, permissions, models, or external peers are available.
Keep lifecycle and configuration in their roles
After the graph is connected, place each part of the operator behavior in the callback that owns it:
| Callback or declaration | Migration responsibility |
|---|---|
setup(OperatorSpec&)
|
Declare typed ports and storage or capacity requirements. |
contract()
|
Declare when the operator may run and which input values it expects. |
compute(ExecutionContext&)
|
Process the data selected for the current activation and return checked errors. |
start() and stop()
|
Acquire and release resources at the lifecycle boundaries defined by the application. |
For a parameterized operator, use Operator<Params> and keep defaults in the parameter type. Apply authoring values before compilation. Read the callback's parameter view through context.params<Params>() when the operator runs. Typed Parameters and Configuration covers the complete configuration path.
Continue with timing after the structure is stable
When the graph and payload inventory are correct, continue with Conditions and Temporal Contracts. That step maps the old conditions and scheduler settings to triggers, input selection, missing-data policies, and completion rules.