2 * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
3 * Distributed under the MIT license (https://opensource.org/licenses/MIT)
6 * @file switch_network_groups_manually_example.c
7 * This example demonstrates basic usage of HailoRT streaming api over multiple network groups, using vstreams.
8 * It loads several HEF networks with a single input and a single output into a Hailo VDevice and performs a inference on each one.
9 * After inference is finished, the example switches to the next HEF and start inference again.
13 #include "hailo_thread.h"
14 #include "hailo/hailort.h"
17 #define MAX_HEF_PATH_LEN (255)
18 #define MAX_EDGE_LAYERS (16)
20 #define INFER_FRAME_COUNT (100)
22 #define RUN_COUNT (10)
23 #define DEVICE_COUNT (1)
25 typedef struct input_vstream_thread_args_t {
26 hailo_configured_network_group *configured_networks;
27 hailo_input_vstream_params_by_name_t *input_vstream_params;
28 } input_vstream_thread_args_t;
30 typedef struct output_vstream_thread_args_t {
31 hailo_configured_network_group *configured_networks;
32 hailo_activated_network_group *activated_network_group;
33 hailo_output_vstream_params_by_name_t *output_vstream_params;
34 } output_vstream_thread_args_t;
36 thread_return_type input_vstream_thread_func(void *args)
38 hailo_status status = HAILO_UNINITIALIZED;
39 hailo_input_vstream input_vstreams[HEF_COUNT];
40 size_t input_frame_size[HEF_COUNT];
41 uint8_t *src_data[HEF_COUNT];
42 input_vstream_thread_args_t *input_vstream_args = (input_vstream_thread_args_t*)args;
44 for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
45 // Input vstream size has to be one in this example- otherwise would haveve returned error
46 status = hailo_create_input_vstreams(input_vstream_args->configured_networks[hef_index],
47 &input_vstream_args->input_vstream_params[hef_index], 1, &input_vstreams[hef_index]);
48 REQUIRE_SUCCESS(status, l_clear_src, "Failed creating virtual stream");
50 status = hailo_get_input_vstream_frame_size(input_vstreams[hef_index], &input_frame_size[hef_index]);
51 REQUIRE_SUCCESS(status, l_clear_src, "Failed getting input virtual stream frame size");
53 src_data[hef_index] = (uint8_t*)malloc(input_frame_size[hef_index]);
54 REQUIRE_ACTION(NULL != src_data[hef_index], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_src, "Out of memory");
57 for (size_t run_index = 0; run_index < RUN_COUNT; run_index++) {
58 for (size_t hef_index = 0 ; hef_index < HEF_COUNT; hef_index++) {
59 // Wait for hef to be activated to send data
60 status = hailo_wait_for_network_group_activation(input_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
61 REQUIRE_SUCCESS(status, l_clear_src, "Failed waiting for network group activation");
63 // Send data on relevant Hef
64 for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
66 for (size_t i = 0; i < input_frame_size[hef_index]; i++) {
67 src_data[hef_index][i] = (uint8_t)(rand() % 256);
70 status = hailo_vstream_write_raw_buffer(input_vstreams[hef_index], src_data[hef_index], input_frame_size[hef_index]);
71 REQUIRE_SUCCESS(status, l_clear_src, "Failed writing input frame to device");
76 status = HAILO_SUCCESS;
79 for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
80 FREE(src_data[hef_index]);
83 (void)hailo_release_input_vstreams(input_vstreams, HEF_COUNT);
84 return (thread_return_type)status;
87 thread_return_type output_vstream_thread_func(void *args)
89 hailo_status status = HAILO_UNINITIALIZED;
90 hailo_output_vstream output_vstreams[HEF_COUNT];
91 size_t output_frame_size[HEF_COUNT];
92 uint8_t *dst_data[HEF_COUNT];
93 output_vstream_thread_args_t *output_vstream_args = (output_vstream_thread_args_t*)args;
95 for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
96 // Output vstream size has to be one in this example- otherwise would haveve returned error
97 status = hailo_create_output_vstreams(output_vstream_args->configured_networks[hef_index],
98 &output_vstream_args->output_vstream_params[hef_index], 1, &output_vstreams[hef_index]);
99 REQUIRE_SUCCESS(status, l_clear_dst, "Failed creating virtual stream");
101 status = hailo_get_output_vstream_frame_size(output_vstreams[hef_index], &output_frame_size[hef_index]);
102 REQUIRE_SUCCESS(status, l_clear_dst, "Failed getting input virtual stream frame size");
104 dst_data[hef_index] = (uint8_t*)malloc(output_frame_size[hef_index]);
105 REQUIRE_ACTION(NULL != dst_data[hef_index], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_dst, "Out of memory");
108 for (size_t run_index = 0; run_index < RUN_COUNT; run_index++) {
109 for (size_t hef_index = 0 ; hef_index < HEF_COUNT; hef_index++) {
110 // Wait for hef to be activated to recv data
111 status = hailo_wait_for_network_group_activation(output_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
112 REQUIRE_SUCCESS(status, l_clear_dst, "Failed waiting for network group activation");
114 for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
116 status = hailo_vstream_read_raw_buffer(output_vstreams[hef_index],
117 dst_data[hef_index], output_frame_size[hef_index]);
118 REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed reading output frame from device");
123 // Deavticate network after finishing inference
124 status = hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
125 REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed Deactivating network");
127 // Dont activate on last iteration
128 if (hef_index < HEF_COUNT - 1) {
129 // Activate next network so input thread can start sending again
130 status = hailo_activate_network_group(output_vstream_args->configured_networks[hef_index + 1],
131 NULL, output_vstream_args->activated_network_group);
132 REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
135 // Meaning we finished a run and now need to activate the first network again for the next run
136 if (run_index < RUN_COUNT - 1) {
137 status = hailo_activate_network_group(output_vstream_args->configured_networks[0],
138 NULL, output_vstream_args->activated_network_group);
139 REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
145 status = HAILO_SUCCESS;
148 l_deactivate_network_group:
149 (void)hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
151 for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
152 FREE(dst_data[hef_index]);
155 (void)hailo_release_output_vstreams(output_vstreams, HEF_COUNT);
156 return (thread_return_type)status;
161 hailo_status status = HAILO_UNINITIALIZED;
162 hailo_vdevice vdevice = NULL;
163 hailo_vdevice_params_t params = {0};
164 hailo_hef hef[HEF_COUNT] = {NULL};
165 hailo_configure_params_t configure_params = {0};
166 hailo_activated_network_group activated_network;
167 hailo_configured_network_group network_groups[HEF_COUNT] = {NULL};
168 size_t network_groups_size = 1;
169 uint8_t hef_index = 0;
170 hailo_input_vstream_params_by_name_t input_vstream_params[HEF_COUNT];
171 hailo_output_vstream_params_by_name_t output_vstream_params[HEF_COUNT];
172 size_t input_vstream_size = 1;
173 size_t output_vstream_size = 1;
175 hailo_thread input_vstream_thread = {0};
176 hailo_thread output_vstream_thread = {0};
177 input_vstream_thread_args_t input_args = {0};
178 output_vstream_thread_args_t output_args = {0};
180 char HEF_FILES[HEF_COUNT][250] = {"hefs/shortcut_net.hef","hefs/shortcut_net.hef"};
182 status = hailo_init_vdevice_params(¶ms);
183 REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
185 params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_NONE;
186 params.device_count = DEVICE_COUNT;
187 status = hailo_create_vdevice(¶ms, &vdevice);
188 REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
190 for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
191 /* Select user HEFs here. In this example it's the same HEF for all networks */
192 status = hailo_create_hef_file(&hef[hef_index], HEF_FILES[hef_index]);
193 REQUIRE_SUCCESS(status, l_release_hef, "Failed creating hef file %s", HEF_FILES[hef_index]);
195 status = hailo_init_configure_params(hef[hef_index], HAILO_STREAM_INTERFACE_PCIE, &configure_params);
196 REQUIRE_SUCCESS(status, l_release_hef, "Failed init configure params");
198 status = hailo_configure_vdevice(vdevice, hef[hef_index], &configure_params, &network_groups[hef_index], &network_groups_size);
199 REQUIRE_SUCCESS(status, l_release_hef, "Failed configuring vdevcie");
200 REQUIRE_ACTION(network_groups_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef,
201 "Unexpected network group size");
203 // Mae sure each hef is single input single output
204 status = hailo_make_input_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
205 &input_vstream_params[hef_index], &input_vstream_size);
206 REQUIRE_SUCCESS(status, l_release_hef, "Failed making input virtual stream params");
207 REQUIRE_ACTION(input_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef,
208 "INVALID HEF - Only hefs with single input vstream are allowed");
210 status = hailo_make_output_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
211 &output_vstream_params[hef_index], &output_vstream_size);
212 REQUIRE_SUCCESS(status, l_release_hef, "Failed making output virtual stream params");
213 REQUIRE_ACTION(output_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef,
214 "INVALID HEF - Only hefs with single output vstream are allowed");
217 input_args.configured_networks = network_groups;
218 input_args.input_vstream_params = input_vstream_params;
220 // Open input vstream and output vstream threads
221 status = hailo_create_thread(input_vstream_thread_func, &input_args, &input_vstream_thread);
222 REQUIRE_SUCCESS(status, l_release_hef, "Failed creating thread");
224 output_args.configured_networks = network_groups;
225 output_args.activated_network_group = &activated_network;
226 output_args.output_vstream_params = output_vstream_params;
228 // Open output vstream and output vstream threads
229 status = hailo_create_thread(output_vstream_thread_func, &output_args, &output_vstream_thread);
230 REQUIRE_SUCCESS(status, l_join_input_thread, "Failed creating thread");
232 // Activate first network so input thread can start
233 status = hailo_activate_network_group(network_groups[0], NULL, &activated_network);
234 REQUIRE_SUCCESS(status, l_join_output_thread, "Failed Activating network");
237 status = hailo_join_thread(&input_vstream_thread);
238 REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for input thread");
240 status = hailo_join_thread(&output_vstream_thread);
241 REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for output thread");
243 printf("Inference ran successfully\n");
244 status = HAILO_SUCCESS;
247 l_join_output_thread:
248 (void)hailo_join_thread(&output_vstream_thread);
250 (void)hailo_join_thread(&input_vstream_thread);
252 for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
253 if (NULL != hef[hef_index]) {
254 (void)hailo_release_hef(hef[hef_index]);
257 (void)hailo_release_vdevice(vdevice);