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 hailo_wait_for_network_group_activation(input_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
62 // Send data on relevant Hef
63 for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
65 for (size_t i = 0; i < input_frame_size[hef_index]; i++) {
66 src_data[hef_index][i] = (uint8_t)(rand() % 256);
69 status = hailo_vstream_write_raw_buffer(input_vstreams[hef_index], src_data[hef_index], input_frame_size[hef_index]);
70 REQUIRE_SUCCESS(status, l_clear_src, "Failed writing input frame to device");
75 status = HAILO_SUCCESS;
78 for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
79 FREE(src_data[hef_index]);
82 (void)hailo_release_input_vstreams(input_vstreams, HEF_COUNT);
83 return (thread_return_type)status;
86 thread_return_type output_vstream_thread_func(void *args)
88 hailo_status status = HAILO_UNINITIALIZED;
89 hailo_output_vstream output_vstreams[HEF_COUNT];
90 size_t output_frame_size[HEF_COUNT];
91 uint8_t *dst_data[HEF_COUNT];
92 output_vstream_thread_args_t *output_vstream_args = (output_vstream_thread_args_t*)args;
94 for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
95 // Output vstream size has to be one in this example- otherwise would haveve returned error
96 status = hailo_create_output_vstreams(output_vstream_args->configured_networks[hef_index],
97 &output_vstream_args->output_vstream_params[hef_index], 1, &output_vstreams[hef_index]);
98 REQUIRE_SUCCESS(status, l_clear_dst, "Failed creating virtual stream");
100 status = hailo_get_output_vstream_frame_size(output_vstreams[hef_index], &output_frame_size[hef_index]);
101 REQUIRE_SUCCESS(status, l_clear_dst, "Failed getting input virtual stream frame size");
103 dst_data[hef_index] = (uint8_t*)malloc(output_frame_size[hef_index]);
104 REQUIRE_ACTION(NULL != dst_data[hef_index], status = HAILO_OUT_OF_HOST_MEMORY, l_clear_dst, "Out of memory");
107 for (size_t run_index = 0; run_index < RUN_COUNT; run_index++) {
108 for (size_t hef_index = 0 ; hef_index < HEF_COUNT; hef_index++) {
109 // Wait for hef to be activated to send data
110 hailo_wait_for_network_group_activation(output_vstream_args->configured_networks[hef_index], HAILO_INFINITE);
112 for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
114 status = hailo_vstream_read_raw_buffer(output_vstreams[hef_index],
115 dst_data[hef_index], output_frame_size[hef_index]);
116 REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed reading output frame from device");
121 // Deavticate network after finishing inference
122 status = hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
123 REQUIRE_SUCCESS(status, l_deactivate_network_group, "Failed Deactivating network");
125 // Dont activate on last iteration
126 if (hef_index < HEF_COUNT - 1) {
127 // Activate next network so input thread can start sending again
128 status = hailo_activate_network_group(output_vstream_args->configured_networks[hef_index + 1],
129 NULL, output_vstream_args->activated_network_group);
130 REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
133 // Meaning we finished a run and now need to activate the first network again for the next run
134 if (run_index < RUN_COUNT - 1) {
135 status = hailo_activate_network_group(output_vstream_args->configured_networks[0],
136 NULL, output_vstream_args->activated_network_group);
137 REQUIRE_SUCCESS(status, l_clear_dst, "Failed Activating network");
143 status = HAILO_SUCCESS;
146 l_deactivate_network_group:
147 (void)hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
149 for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
150 FREE(dst_data[hef_index]);
153 (void)hailo_release_output_vstreams(output_vstreams, HEF_COUNT);
154 return (thread_return_type)status;
159 hailo_status status = HAILO_UNINITIALIZED;
160 hailo_vdevice vdevice = NULL;
161 hailo_vdevice_params_t params = {0};
162 hailo_hef hef[HEF_COUNT] = {NULL};
163 hailo_configure_params_t configure_params = {0};
164 hailo_activated_network_group activated_network;
165 hailo_configured_network_group network_groups[HEF_COUNT] = {NULL};
166 size_t network_groups_size = 1;
167 uint8_t hef_index = 0;
168 hailo_input_vstream_params_by_name_t input_vstream_params[HEF_COUNT];
169 hailo_output_vstream_params_by_name_t output_vstream_params[HEF_COUNT];
170 size_t input_vstream_size = 1;
171 size_t output_vstream_size = 1;
173 hailo_thread input_vstream_thread = {0};
174 hailo_thread output_vstream_thread = {0};
175 input_vstream_thread_args_t input_args = {0};
176 output_vstream_thread_args_t output_args = {0};
178 char HEF_FILES[HEF_COUNT][250] = {"hefs/shortcut_net.hef","hefs/shortcut_net.hef"};
180 status = hailo_init_vdevice_params(¶ms);
181 REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
183 params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_NONE;
184 params.device_count = DEVICE_COUNT;
185 status = hailo_create_vdevice(¶ms, &vdevice);
186 REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
188 for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
189 /* Select user HEFs here. In this example it's the same HEF for all networks */
190 status = hailo_create_hef_file(&hef[hef_index], HEF_FILES[hef_index]);
191 REQUIRE_SUCCESS(status, l_release_hef, "Failed creating hef file %s", HEF_FILES[hef_index]);
193 status = hailo_init_configure_params(hef[hef_index], HAILO_STREAM_INTERFACE_PCIE, &configure_params);
194 REQUIRE_SUCCESS(status, l_release_hef, "Failed init configure params");
196 status = hailo_configure_vdevice(vdevice, hef[hef_index], &configure_params, &network_groups[hef_index], &network_groups_size);
197 REQUIRE_SUCCESS(status, l_release_hef, "Failed configuring vdevcie");
198 REQUIRE_ACTION(network_groups_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef,
199 "Unexpected network group size");
201 // Mae sure each hef is single input single output
202 status = hailo_make_input_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
203 &input_vstream_params[hef_index], &input_vstream_size);
204 REQUIRE_SUCCESS(status, l_release_hef, "Failed making input virtual stream params");
205 REQUIRE_ACTION(input_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef,
206 "INVALID HEF - Only hefs with single input vstream are allowed");
208 status = hailo_make_output_vstream_params(network_groups[hef_index], true, HAILO_FORMAT_TYPE_AUTO,
209 &output_vstream_params[hef_index], &output_vstream_size);
210 REQUIRE_SUCCESS(status, l_release_hef, "Failed making output virtual stream params");
211 REQUIRE_ACTION(output_vstream_size == 1, status = HAILO_INVALID_ARGUMENT, l_release_hef,
212 "INVALID HEF - Only hefs with single output vstream are allowed");
215 input_args.configured_networks = network_groups;
216 input_args.input_vstream_params = input_vstream_params;
218 // Open input vstream and output vstream threads
219 status = hailo_create_thread(input_vstream_thread_func, &input_args, &input_vstream_thread);
220 REQUIRE_SUCCESS(status, l_release_hef, "Failed creating thread");
222 output_args.configured_networks = network_groups;
223 output_args.activated_network_group = &activated_network;
224 output_args.output_vstream_params = output_vstream_params;
226 // Open output vstream and output vstream threads
227 status = hailo_create_thread(output_vstream_thread_func, &output_args, &output_vstream_thread);
228 REQUIRE_SUCCESS(status, l_join_input_thread, "Failed creating thread");
230 // Activate first network so input thread can start
231 status = hailo_activate_network_group(network_groups[0], NULL, &activated_network);
232 REQUIRE_SUCCESS(status, l_join_output_thread, "Failed Activating network");
235 status = hailo_join_thread(&input_vstream_thread);
236 REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for input thread");
238 status = hailo_join_thread(&output_vstream_thread);
239 REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for output thread");
241 printf("Inference ran successfully\n");
242 status = HAILO_SUCCESS;
245 l_join_output_thread:
246 (void)hailo_join_thread(&output_vstream_thread);
248 (void)hailo_join_thread(&input_vstream_thread);
250 for (hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
251 if (NULL != hef[hef_index]) {
252 (void)hailo_release_hef(hef[hef_index]);
255 (void)hailo_release_vdevice(vdevice);