5d56190f9601c589c681ec15832aabfa336d3d3b
[platform/upstream/hailort.git] /
1 /**
2  * Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
3  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
4  **/
5 /**
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.
10  **/
11
12 #include "common.h"
13 #include "hailo_thread.h"
14 #include "hailo/hailort.h"
15 #include <time.h>
16
17 #define MAX_HEF_PATH_LEN (255)
18 #define MAX_EDGE_LAYERS (16)
19
20 #define INFER_FRAME_COUNT (100)
21 #define HEF_COUNT (2)
22 #define RUN_COUNT (10)
23 #define DEVICE_COUNT (1)
24
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;
29
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;
35
36 thread_return_type input_vstream_thread_func(void *args)
37 {
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;
43
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");
49
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");
52
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");
55     }
56
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);
61
62             // Send data on relevant Hef
63             for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
64                 // Prepare data here
65                 for (size_t i = 0; i < input_frame_size[hef_index]; i++) {
66                     src_data[hef_index][i] = (uint8_t)(rand() % 256);
67                 }
68
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");
71             }
72         }
73     }
74
75     status = HAILO_SUCCESS;
76
77 l_clear_src:
78     for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
79         FREE(src_data[hef_index]);
80     }
81
82     (void)hailo_release_input_vstreams(input_vstreams, HEF_COUNT);
83     return (thread_return_type)status;
84 }
85
86 thread_return_type output_vstream_thread_func(void *args)
87 {
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;
93
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");
99
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");
102
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");
105     }
106
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);
111     
112             for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
113                 // Read data
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");
117     
118                 // Process data here
119             }
120     
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");
124     
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");
131             }
132             else {
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");
138                 }
139             }
140         }
141     }
142
143     status = HAILO_SUCCESS;
144     goto l_clear_dst;
145
146 l_deactivate_network_group:
147     (void)hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
148 l_clear_dst:
149     for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
150         FREE(dst_data[hef_index]);
151     }
152
153     (void)hailo_release_output_vstreams(output_vstreams, HEF_COUNT);
154     return (thread_return_type)status;
155 }
156
157 int main()
158 {
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;
172
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};
177
178     char HEF_FILES[HEF_COUNT][250] = {"hefs/shortcut_net.hef","hefs/shortcut_net.hef"};
179
180     status = hailo_init_vdevice_params(&params);
181     REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
182
183     params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_NONE;
184     params.device_count = DEVICE_COUNT;
185     status = hailo_create_vdevice(&params, &vdevice);
186     REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
187
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]);
192
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");
195
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");
200
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");
207
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");
213     }
214
215     input_args.configured_networks      = network_groups;
216     input_args.input_vstream_params     = input_vstream_params;
217
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");
221
222     output_args.configured_networks         = network_groups;
223     output_args.activated_network_group     = &activated_network;
224     output_args.output_vstream_params       = output_vstream_params;
225
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");
229
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");
233
234
235     status = hailo_join_thread(&input_vstream_thread);
236     REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for input thread");
237
238     status = hailo_join_thread(&output_vstream_thread);
239     REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for output thread");
240
241     printf("Inference ran successfully\n");
242     status = HAILO_SUCCESS;
243     goto l_release_hef;
244
245 l_join_output_thread:
246     (void)hailo_join_thread(&output_vstream_thread);
247 l_join_input_thread:
248     (void)hailo_join_thread(&input_vstream_thread);
249 l_release_hef:
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]);            
253         }
254     }
255     (void)hailo_release_vdevice(vdevice);
256 l_exit:
257     return status;
258 }