Class Application

class Application : public holoscan::Fragment

Application class.

An application acquires and processes streaming data. An application is a collection of fragments where each fragment can be allocated to execute on a physical node of a Holoscan cluster.

Public Functions

Application() = default

~Application() override = default

template<typename FragmentT = Fragment, typename StringT, typename ...ArgsT, typename = std::enable_if_t<std::is_constructible_v<std::string, StringT>>>
inline std::shared_ptr<Fragment> make_fragment(const StringT &name, ArgsT&&... args)

Create a new fragment.

Template Parameters

FragmentT – The type of the fragment to create.

Parameters
  • name – The name of the fragment.

  • args – The arguments to pass to the fragment constructor.

Returns

The shared pointer to the created fragment.

template<typename FragmentT, typename ...ArgsT>
inline std::shared_ptr<FragmentT> make_fragment(ArgsT&&... args)

Create a new fragment.

Template Parameters

FragmentT – The type of the fragment to create.

Parameters

args – The arguments to pass to the fragment constructor.

Returns

The shared pointer to the created fragment.

inline virtual void add_flow(const std::shared_ptr<Fragment> &upstream_frag, const std::shared_ptr<Fragment> &downstream_frag)

inline virtual void add_flow(const std::shared_ptr<Fragment> &upstream_frag, const std::shared_ptr<Fragment> &downstream_frag, const std::set<std::pair<std::string, std::string>> &port_pairs)

virtual void add_flow(const std::shared_ptr<Operator> &upstream_op, const std::shared_ptr<Operator> &downstream_op)

Add a flow between two operators.

An output port of the upstream operator is connected to an input port of the downstream operator. The information about the flow (edge) is stored in the Graph object.

If the upstream operator or the downstream operator is not in the graph, it will be added to the graph.

If there are multiple output ports in the upstream operator or multiple input ports in the downstream operator, it shows an error message.

Parameters
  • upstream_op – The upstream operator.

  • downstream_op – The downstream operator.

virtual void add_flow(const std::shared_ptr<Operator> &upstream_op, const std::shared_ptr<Operator> &downstream_op, std::set<std::pair<std::string, std::string>> port_pairs)

Add a flow between two operators.

An output port of the upstream operator is connected to an input port of the downstream operator. The information about the flow (edge) is stored in the Graph object.

If the upstream operator or the downstream operator is not in the graph, it will be added to the graph.

In port_pairs, an empty port name (“”) can be used for specifying a port name if the operator has only one input/output port.

If a non-existent port name is specified in port_pairs, it first checks if there is a parameter with the same name but with a type of std::vector<holoscan::IOSpec*> in the downstream operator. If there is such a parameter (e.g., receivers), it creates a new input port with a specific label (<parameter name>:<index>. e.g., receivers:0), otherwise it shows an error message.

For example, if a parameter receivers want to have an arbitrary number of receivers,

Copy
Copied!
            

class HolovizOp : public holoscan::ops::GXFOperator { ... private: Parameter<std::vector<holoscan::IOSpec*>> receivers_; ...

Instead of creating a fixed number of input ports (e.g., source_video and tensor) and assigning them to the parameter (receivers):

Copy
Copied!
            

void HolovizOp::setup(OperatorSpec& spec) { ... auto& in_source_video = spec.input<holoscan::gxf::Entity>("source_video"); auto& in_tensor = spec.input<holoscan::gxf::Entity>("tensor"); spec.param(receivers_, "receivers", "Input Receivers", "List of input receivers.", {&in_source_video, &in_tensor}); ...

You can skip the creation of input ports and assign them to the parameter (receivers) as follows:

Copy
Copied!
            

void HolovizOp::setup(OperatorSpec& spec) { ... spec.param(receivers_, "receivers", "Input Receivers", "List of input receivers.", {&in_source_video, &in_tensor}); ...

This makes the following code possible in the Application’s compose() method:

Copy
Copied!
            

add_flow(source, visualizer_format_converter); add_flow(visualizer_format_converter, visualizer, {{"", "receivers"}}); add_flow(source, format_converter); add_flow(format_converter, lstm_inferer); add_flow(lstm_inferer, visualizer, {{"", "receivers"}});

Instead of:

Copy
Copied!
            

add_flow(source, visualizer_format_converter); add_flow(visualizer_format_converter, visualizer, {{"", "source_video"}}); add_flow(source, format_converter); add_flow(format_converter, lstm_inferer); add_flow(lstm_inferer, visualizer, {{"", "tensor"}});

By using the parameter (receivers) with std::vector<holoscan::IOSpec*> type, the framework creates input ports (receivers:0 and receivers:1) implicitly and connects them (and adds the references of the input ports to the receivers vector).

Parameters
  • upstream_op – The upstream operator.

  • downstream_op – The downstream operator.

  • port_pairs – The port pairs. The first element of the pair is the port of the upstream operator and the second element is the port of the downstream operator.

© Copyright 2022, NVIDIA. Last updated on Jun 28, 2023.