f7872e05978e8d27949744765b2fe16201fe87d3
[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             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");
62
63             // Send data on relevant Hef
64             for (uint32_t frame = 0; frame < INFER_FRAME_COUNT; frame++) {
65                 // Prepare data here
66                 for (size_t i = 0; i < input_frame_size[hef_index]; i++) {
67                     src_data[hef_index][i] = (uint8_t)(rand() % 256);
68                 }
69
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");
72             }
73         }
74     }
75
76     status = HAILO_SUCCESS;
77
78 l_clear_src:
79     for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
80         FREE(src_data[hef_index]);
81     }
82
83     (void)hailo_release_input_vstreams(input_vstreams, HEF_COUNT);
84     return (thread_return_type)status;
85 }
86
87 thread_return_type output_vstream_thread_func(void *args)
88 {
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;
94
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");
100
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");
103
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");
106     }
107
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");
113
114             for (uint32_t i = 0; i < INFER_FRAME_COUNT; i++) {
115                 // Read data
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");
119     
120                 // Process data here
121             }
122     
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");
126     
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");
133             }
134             else {
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");
140                 }
141             }
142         }
143     }
144
145     status = HAILO_SUCCESS;
146     goto l_clear_dst;
147
148 l_deactivate_network_group:
149     (void)hailo_deactivate_network_group(*(output_vstream_args->activated_network_group));
150 l_clear_dst:
151     for (size_t hef_index = 0; hef_index < HEF_COUNT; hef_index++) {
152         FREE(dst_data[hef_index]);
153     }
154
155     (void)hailo_release_output_vstreams(output_vstreams, HEF_COUNT);
156     return (thread_return_type)status;
157 }
158
159 int main()
160 {
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;
174
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};
179
180     char HEF_FILES[HEF_COUNT][250] = {"hefs/shortcut_net.hef","hefs/shortcut_net.hef"};
181
182     status = hailo_init_vdevice_params(&params);
183     REQUIRE_SUCCESS(status, l_exit, "Failed init vdevice_params");
184
185     params.scheduling_algorithm = HAILO_SCHEDULING_ALGORITHM_NONE;
186     params.device_count = DEVICE_COUNT;
187     status = hailo_create_vdevice(&params, &vdevice);
188     REQUIRE_SUCCESS(status, l_exit, "Failed to create vdevice");
189
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]);
194
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");
197
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");
202
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");
209
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");
215     }
216
217     input_args.configured_networks      = network_groups;
218     input_args.input_vstream_params     = input_vstream_params;
219
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");
223
224     output_args.configured_networks         = network_groups;
225     output_args.activated_network_group     = &activated_network;
226     output_args.output_vstream_params       = output_vstream_params;
227
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");
231
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");
235
236
237     status = hailo_join_thread(&input_vstream_thread);
238     REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for input thread");
239
240     status = hailo_join_thread(&output_vstream_thread);
241     REQUIRE_SUCCESS(status, l_join_output_thread, "Failed witing for output thread");
242
243     printf("Inference ran successfully\n");
244     status = HAILO_SUCCESS;
245     goto l_release_hef;
246
247 l_join_output_thread:
248     (void)hailo_join_thread(&output_vstream_thread);
249 l_join_input_thread:
250     (void)hailo_join_thread(&input_vstream_thread);
251 l_release_hef:
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]);            
255         }
256     }
257     (void)hailo_release_vdevice(vdevice);
258 l_exit:
259     return status;
260 }