npu_sink_src_test.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /* auto generate by HHB_VERSION "2.0.21" */
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdint.h>
  24. #include <libgen.h>
  25. #include <unistd.h>
  26. #include <fcntl.h>
  27. #include <sys/mman.h>
  28. #include <pthread.h>
  29. #include <memory.h>
  30. #include "process_linker_types.h"
  31. #include "io.h"
  32. #include "shl_ref.h"
  33. #include "process.h"
  34. #include "video_mem.h"
  35. #include "detect.h"
  36. #include "output_120_out0_nchw_1_2_7668_1.h"
  37. #define MODULE_NAME "npu_sink_src_test"
  38. #define MIN(x, y) ((x) < (y) ? (x) : (y))
  39. #define FILE_LENGTH 1028
  40. #define SHAPE_LENGHT 128
  41. #ifndef NULL
  42. #define NULL ((void *)0)
  43. #endif
  44. #define NUM_OF_BUFFERS 5
  45. #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
  46. } while (0)
  47. void *csinn_(char *params);
  48. void csinn_run(void *data0, void *td);
  49. void *csinn_nbg(const char *nbg_file_name);
  50. #define OUT_SIZE1 (1*7668)
  51. #define OUT_SIZE2 (1917*21)
  52. int input_size[] = {1 * 3 * 304 * 304, };
  53. int output_size[] = {OUT_SIZE1, OUT_SIZE1 * 2, 1 * OUT_SIZE2, };
  54. const char model_name[] = "network";
  55. #define R_MEAN 127.5
  56. #define G_MEAN 127.5
  57. #define B_MEAN 127.5
  58. #define SCALE (1.0/127.5)
  59. float mean[] = {B_MEAN, G_MEAN, R_MEAN};
  60. const char class_name[][FILE_LENGTH] = {
  61. "background", "aeroplane", "bicycle", "bird", "boat",
  62. "bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
  63. "dog", "horse", "motorbike", "person", "pottedplant", "sheep",
  64. "sofa", "train", "tvmonitor"
  65. };
  66. const char shm_sink_name[] = "/ispnpu";
  67. const char shm_src_name[] = "/npu_g2d";
  68. #define BASE_MEMORY 0xD8000000
  69. typedef struct _ServerParams
  70. {
  71. char *plinkname;
  72. int count;
  73. int frames;
  74. } ServerParams;
  75. typedef struct _PlinkChannel
  76. {
  77. PlinkChannelID id;
  78. PlinkHandle plink;
  79. PlinkPacket pkt;
  80. int sendid;
  81. int backid;
  82. int exit;
  83. int available_bufs;
  84. } PlinkChannel;
  85. typedef struct _FeatureBuffer {
  86. unsigned int bus_address;
  87. void *virtual_address;
  88. unsigned int size;
  89. } FeatureBuffer;
  90. void parseParams(int argc, char **argv, ServerParams *params)
  91. {
  92. int i = 1;
  93. memset(params, 0, sizeof(*params));
  94. params->plinkname = "/tmp/plink_npu_featuremap.test";
  95. params->frames = 3;
  96. while (i < argc)
  97. {
  98. if (argv[i][0] != '-' || strlen(argv[i]) < 2)
  99. {
  100. i++;
  101. continue;
  102. }
  103. if (argv[i][1] == 'l')
  104. {
  105. if (++i < argc)
  106. {
  107. params->plinkname = argv[i++];
  108. }
  109. }
  110. else if (argv[i][1] == 'n')
  111. {
  112. if (++i < argc)
  113. {
  114. params->frames = atoi(argv[i++]);
  115. }
  116. }
  117. };
  118. }
  119. int checkParams(ServerParams *params)
  120. {
  121. if (params->plinkname == NULL)
  122. return -1;
  123. return 0;
  124. }
  125. void printUsage(char *name)
  126. {
  127. printf("usage: %s [options]\n"
  128. "\n"
  129. " Available options:\n"
  130. " -l plink file name (default: /tmp/plink.test)\n"
  131. " -i input YUV file name (mandatory)\n"
  132. " -f input color format (default: 2)\n"
  133. " 2 - I420\n"
  134. " 3 - NV12\n"
  135. " -w video width (mandatory)\n"
  136. " -h video height (mandatory)\n"
  137. " -s video buffer stride (default: video width)\n"
  138. " -n number of frames to send (default: 10)\n"
  139. "\n", name);
  140. }
  141. int getBufferSize(ServerParams *params)
  142. {
  143. return sizeof(PlinkObjectDetect);
  144. }
  145. void constructFeatureInfo(PlinkObjectInfo *info, ServerParams *params, unsigned int bus_address, int face_cnt, int id)
  146. {
  147. info->header.type = PLINK_TYPE_OBJECT;
  148. info->header.size = DATA_SIZE(*info);
  149. info->header.id = id + 1;
  150. info->bus_address = bus_address;
  151. info->object_cnt = face_cnt;
  152. }
  153. int getBufferCount(PlinkPacket *pkt)
  154. {
  155. int ret = 0;
  156. for (int i = 0; i < pkt->num; i++)
  157. {
  158. PlinkDescHdr *hdr = (PlinkDescHdr *)(pkt->list[i]);
  159. if (hdr->type == PLINK_TYPE_MESSAGE)
  160. {
  161. int *data = (int *)(pkt->list[i] + DATA_HEADER_SIZE);
  162. if (*data == PLINK_EXIT_CODE)
  163. {
  164. ret |= 0x80000000; // set bit 31 to 1 to indicate 'exit'
  165. }
  166. else if (*data >= 0)
  167. ret++;
  168. }
  169. }
  170. return ret;
  171. }
  172. void retreiveSentBuffers(PlinkHandle plink, PlinkChannel *channel)
  173. {
  174. PlinkStatus sts = PLINK_STATUS_OK;
  175. while (channel->available_bufs < NUM_OF_BUFFERS)
  176. {
  177. do
  178. {
  179. sts = PLINK_recv(plink, channel->id, &channel->pkt);
  180. int count = getBufferCount(&channel->pkt);
  181. if (count > 0)
  182. {
  183. channel->available_bufs += count;
  184. }
  185. } while (sts == PLINK_STATUS_MORE_DATA);
  186. }
  187. }
  188. void AllocateBuffers(FeatureBuffer featurebuffers[NUM_OF_BUFFERS], unsigned int size, int fd_mem) {
  189. unsigned int bus_address = BASE_MEMORY;
  190. unsigned int buffer_size = (size + 0xFFF) & ~0xFFF;
  191. for (int i = 0; i < NUM_OF_BUFFERS; i++) {
  192. featurebuffers[i].virtual_address = mmap(0, buffer_size, PROT_READ | PROT_WRITE,
  193. MAP_SHARED, fd_mem,
  194. bus_address);
  195. printf("mmap %p from %x with size %d\n", featurebuffers[i].virtual_address, bus_address, size);
  196. featurebuffers[i].bus_address = bus_address;
  197. featurebuffers[i].size = buffer_size;
  198. bus_address += buffer_size;
  199. }
  200. }
  201. void FreeBuffers(FeatureBuffer featurebuffers[NUM_OF_BUFFERS], unsigned int size, int fd_mem) {
  202. for (int i = 0; i < NUM_OF_BUFFERS; i++) {
  203. munmap(featurebuffers[i].virtual_address, featurebuffers[i].size);
  204. }
  205. }
  206. static void print_tensor_info(struct csinn_tensor *t) {
  207. printf("\n=== tensor info ===\n");
  208. printf("shape: ");
  209. for (int j = 0; j < t->dim_count; j++) {
  210. printf("%d ", t->dim[j]);
  211. }
  212. printf("\n");
  213. if (t->dtype == CSINN_DTYPE_UINT8) {
  214. printf("scale: %f\n", t->qinfo->scale);
  215. printf("zero point: %d\n", t->qinfo->zero_point);
  216. }
  217. printf("data pointer: %p\n", t->data);
  218. }
  219. /*
  220. * Postprocess function
  221. */
  222. static void postprocess(void *sess, const char *filename_prefix, BBoxOut *out, int *num) {
  223. int output_num, input_num;
  224. struct csinn_tensor *input = csinn_alloc_tensor(NULL);
  225. struct csinn_tensor *output = csinn_alloc_tensor(NULL);
  226. //input_num = csinn_get_input_number(sess);
  227. //for (int i = 0; i < input_num; i++) {
  228. // input->data = NULL;
  229. // csinn_get_input(i, input, sess);
  230. // //print_tensor_info(input);
  231. // struct csi_tensor *finput = shl_ref_tensor_transform_f32(input);
  232. // char filename[FILE_LENGTH] = {0};
  233. // char shape[SHAPE_LENGHT] = {0};
  234. // shape2string(input->dim, input->dim_count, shape, SHAPE_LENGHT);
  235. // snprintf(filename, FILE_LENGTH, "%s_input%u_%s.txt", filename_prefix, i, shape);
  236. // int input_size = csi_tensor_size(input);
  237. //printf("input_size: %d\n", input_size);
  238. //save_data_to_file(filename, (float*)finput->data, input_size);
  239. //}
  240. float *location = (float*)malloc(OUT_SIZE1*sizeof(float));
  241. float *confidence = (float*)malloc(OUT_SIZE2*sizeof(float));
  242. output_num = csinn_get_output_number(sess);
  243. for (int i = 0; i < output_num; i++) {
  244. output->data = NULL;
  245. csinn_get_output(i, output, sess);
  246. //print_tensor_info(output);
  247. struct csinn_tensor *foutput = shl_ref_tensor_transform_f32(output);
  248. //shl_show_top5(foutput, sess);
  249. //char filename[FILE_LENGTH] = {0};
  250. //char shape[SHAPE_LENGHT] = {0};
  251. //shape2string(output->dim, output->dim_count, shape, SHAPE_LENGHT);
  252. //snprintf(filename, FILE_LENGTH, "%s_output%u_%s.txt", filename_prefix, i, shape);
  253. //int output_size = csinn_tensor_size(foutput);
  254. //save_data_to_file(filename, (float*)foutput->data, output_size);
  255. if (i == 0)
  256. memcpy(location, (float *)foutput->data, OUT_SIZE1*sizeof(float));
  257. if (i == 1)
  258. memcpy(confidence, (float *)foutput->data, OUT_SIZE2*sizeof(float));
  259. shl_ref_tensor_transform_free_f32(foutput);
  260. }
  261. //BBoxOut out[100];
  262. BBox gbboxes[num_prior];
  263. *num = ssdforward(location, confidence, priorbox, gbboxes, out);
  264. free(location);
  265. free(confidence);
  266. printf("%d\n", *num);
  267. for (int i = 0; i < *num; i++) {
  268. fprintf(stderr, "%d, label=%s, score=%f, x1=%f, y1=%f, x2=%f, y2=%f\n", out[i].label, class_name[out[i].label],
  269. out[i].score, out[i].xmin, out[i].ymin, out[i].xmax, out[i].ymax);
  270. }
  271. csinn_free_tensor(input);
  272. csinn_free_tensor(output);
  273. }
  274. void *create_graph(char *params_path) {
  275. void *ret;
  276. int binary_size;
  277. char *params = get_binary_from_file(params_path, &binary_size);
  278. if (params == NULL) {
  279. return NULL;
  280. }
  281. char *suffix = params_path + (strlen(params_path) - 7);
  282. if (strcmp(suffix, ".params") == 0) {
  283. // create general graph
  284. ret = csinn_(params);
  285. free(params);
  286. return ret;
  287. }
  288. suffix = params_path + (strlen(params_path) - 3);
  289. if (strcmp(suffix, ".bm") == 0) {
  290. struct shl_bm_sections *section = (struct shl_bm_sections *)(params + 4128);
  291. if (section->graph_offset) {
  292. ret = csinn_import_binary_model(params);
  293. free(params);
  294. return ret;
  295. } else {
  296. ret = csinn_(params + section->params_offset * 4096);
  297. free(params);
  298. return ret;
  299. }
  300. } else {
  301. free(params);
  302. return NULL;
  303. }
  304. }
  305. bool is_looping = true;
  306. int main(int argc, char **argv) {
  307. char **data_path = NULL;
  308. char *params_path = NULL;
  309. int input_num = 1;
  310. int output_num = 3;
  311. int input_group_num = 1;
  312. int index = 0;
  313. int export_index = 0;
  314. PlinkStatus sts = PLINK_STATUS_OK;
  315. PlinkPacket sendpkt, recvpkt;
  316. PlinkMsg msg;
  317. PlinkHandle plink_npu_sink = NULL;
  318. PlinkHandle plink_npu_src = NULL;
  319. ServerParams params;
  320. VmemParams vmem_params;
  321. void *vmem = NULL;
  322. PlinkChannel channel[2];
  323. PlinkObjectInfo feat_map;
  324. FILE *fp = NULL;
  325. int exitcode = 0;
  326. int i;
  327. if (argc < (2 + input_num)) {
  328. printf("Please set valide args: ./model.elf model.params "
  329. "[tensor1/image1 ...] [tensor2/image2 ...]\n");
  330. return -1;
  331. } else {
  332. if (argc == 3 && get_file_type(argv[2]) == FILE_TXT) {
  333. data_path = read_string_from_file(argv[2], &input_group_num);
  334. input_group_num /= input_num;
  335. } else {
  336. data_path = argv + 2;
  337. input_group_num = (argc - 2) / input_num;
  338. }
  339. }
  340. parseParams(argc, argv, &params);
  341. if (checkParams(&params) != 0)
  342. {
  343. printUsage(argv[0]);
  344. return 0;
  345. }
  346. void *sess = create_graph(argv[1]);
  347. uint8_t *input[input_num];
  348. float *finput[input_num];
  349. char filename_prefix[FILE_LENGTH] = {0};
  350. void *input_aligned[input_num];
  351. for (i = 0; i < input_num; i++) {
  352. input_aligned[i] = shl_mem_alloc_aligned(input_size[i], 0);
  353. }
  354. uint64_t start_time, end_time;
  355. uint64_t _start_time, _end_time;
  356. //int frames = argc > 1 ? atoi(argv[1]) : 1000;
  357. int frames = 1000;
  358. //char *dumpname = argc > 2 ? argv[2] : NULL;
  359. char *dumpname = NULL;
  360. if (dumpname != NULL)
  361. {
  362. fp = fopen(dumpname, "wb");
  363. if (fp == NULL)
  364. errExit("fopen");
  365. }
  366. if (VMEM_create(&vmem) != VMEM_STATUS_OK)
  367. errExit("Failed to create VMEM.");
  368. int fd_mem = open("/dev/mem", O_RDWR | O_SYNC);
  369. if (fd_mem == -1) {
  370. printf("ERROR: failed to open: %s\n", "/dev/mem");
  371. return -1;
  372. }
  373. int fd_src_mem = open("/dev/mem", O_RDWR | O_SYNC);
  374. if (fd_src_mem < 0) {
  375. printf("%s: failed to open /dev/mem", MODULE_NAME);
  376. return -1;
  377. }
  378. BBoxOut out[100];
  379. int out_num = 0;
  380. FeatureBuffer featurebuffers[NUM_OF_BUFFERS];
  381. AllocateBuffers(featurebuffers, 100 * sizeof(struct _FeatureBuffer), fd_mem);
  382. printf("PLINK begin to create & connect /tmp/plink_npu_rgb.test\n");
  383. if (PLINK_create(&plink_npu_sink, "/tmp/plink_npu_rgb.test", PLINK_MODE_CLIENT) != PLINK_STATUS_OK)
  384. errExit("Failed to create PLINK.");
  385. if (PLINK_connect(plink_npu_sink, NULL) != PLINK_STATUS_OK)
  386. errExit("Failed to connect to server.");
  387. printf("PLINK begin to create & connect %s\n", params.plinkname);
  388. sts = PLINK_create(&plink_npu_src, params.plinkname, PLINK_MODE_SERVER);
  389. memset(&channel[0], 0, sizeof(channel[0]));
  390. channel[0].available_bufs = NUM_OF_BUFFERS;
  391. sts = PLINK_connect(plink_npu_src, &channel[0].id);
  392. printf("begin to loops\n");
  393. int frmcnt = 0;
  394. // while loop to receive shm picture
  395. do {
  396. sts = PLINK_recv(plink_npu_sink, 0, &recvpkt);
  397. memset(&vmem_params, 0, sizeof(vmem_params));
  398. if (recvpkt.fd != PLINK_INVALID_FD) { // dmabuf fd
  399. vmem_params.fd = recvpkt.fd;
  400. if (VMEM_import(vmem, &vmem_params) != VMEM_STATUS_OK)
  401. errExit("Failed to import fd.");
  402. printf("%s: recvpkt.fd<%d> phy<0x%lx>\n", MODULE_NAME, vmem_params.fd, vmem_params.phy_address);
  403. }
  404. for (i = 0; i < recvpkt.num; i++) {
  405. PlinkDescHdr *hdr = (PlinkDescHdr *)(recvpkt.list[i]);
  406. if (hdr->type == PLINK_TYPE_2D_RGB) {
  407. uint8_t *vaddr = 0;
  408. PlinkRGBInfo *pic = (PlinkRGBInfo *)(recvpkt.list[i]);
  409. printf("[CLIENT] Received frame %d 0x%010llx: %dx%d, stride = %d\n",
  410. pic->header.id, pic->bus_address_b,
  411. pic->img_width, pic->img_height,
  412. pic->stride_b);
  413. int size_stride = 3 * pic->stride_b * pic->stride_b;
  414. if (recvpkt.fd == PLINK_INVALID_FD) { // physical address
  415. vaddr = (uint8_t *) mmap(0, size_stride, PROT_READ | PROT_WRITE,
  416. MAP_SHARED, fd_mem, pic->bus_address_b);
  417. }
  418. // return the buffer to source
  419. msg.header.type = PLINK_TYPE_MESSAGE;
  420. msg.header.size = DATA_SIZE(PlinkMsg);
  421. msg.msg = hdr->id;
  422. sendpkt.list[0] = &msg;
  423. sendpkt.num = 1;
  424. sendpkt.fd = PLINK_INVALID_FD;
  425. if (PLINK_send(plink_npu_sink, 0, &sendpkt) == PLINK_STATUS_ERROR)
  426. errExit("Failed to send data.");
  427. _start_time = shl_get_timespec();
  428. if (recvpkt.fd == PLINK_INVALID_FD) { // physical address
  429. csinn_run(vaddr, sess);
  430. } else {
  431. csinn_run(&vmem_params.fd, sess);
  432. }
  433. _end_time = shl_get_timespec();
  434. printf("Run graph execution time: %.5fms, FPS=%.2f\n", ((float)(_end_time-_start_time))/1000000,
  435. 1000000000.0/((float)(_end_time-_start_time)));
  436. //snprintf(filename_prefix, FILE_LENGTH, "%s", basename(data_path[i * input_num]));
  437. _start_time = shl_get_timespec();
  438. postprocess(sess, filename_prefix, out, &out_num);
  439. _end_time = shl_get_timespec();
  440. printf("postProcess execution time: %.5fms\n", ((float)(_end_time-_start_time))/1000000);
  441. if (recvpkt.fd == PLINK_INVALID_FD) // physical address
  442. munmap(vaddr, size_stride);
  443. int sendid = channel[0].sendid;
  444. int face_cnt = 0;
  445. float *ptr = (float *)featurebuffers[sendid].virtual_address;
  446. for (int i = 0; i < out_num; i++) {
  447. if (strcmp(class_name[out[i].label], "person") == 0) {
  448. // ignore rects too low or too fat
  449. //if ((out[i].ymin > 0.3) || ((out[i].ymax - out[i].ymin) < (out[i].xmax - out[i].xmin)))
  450. // continue;
  451. face_cnt++;
  452. *ptr++ = out[i].score;
  453. *ptr++ = out[i].xmin;
  454. *ptr++ = out[i].ymin;
  455. *ptr++ = out[i].xmax;
  456. *ptr++ = out[i].ymax;
  457. *ptr++ = -1;
  458. *ptr++ = -1;
  459. *ptr++ = -1;
  460. *ptr++ = -1;
  461. *ptr++ = -1;
  462. *ptr++ = -1;
  463. *ptr++ = -1;
  464. *ptr++ = -1;
  465. *ptr++ = -1;
  466. *ptr++ = -1;
  467. }
  468. }
  469. if (face_cnt > 0) {
  470. constructFeatureInfo(&feat_map, &params, featurebuffers[sendid].bus_address, face_cnt, sendid);
  471. printf("[FeatureMap SERVER] Processed frame %d 0x%08x: %d\n",
  472. sendid, feat_map.bus_address, face_cnt);
  473. channel[0].pkt.list[0] = &feat_map;
  474. channel[0].pkt.num = 1;
  475. //channel[0].pkt.fd = picbuffers[sendid].fd;
  476. channel[0].pkt.fd = PLINK_INVALID_FD; // physical address
  477. sts = PLINK_send(plink_npu_src, channel[0].id, &channel[0].pkt);
  478. channel[0].sendid = (channel[0].sendid + 1) % NUM_OF_BUFFERS;
  479. channel[0].available_bufs -= 1;
  480. // Notify npu one picture is ready for inference
  481. int timeout = 0;
  482. if (channel[0].available_bufs == 0)
  483. timeout = 60000; // wait up to 60 seconds if buffers are used up
  484. if (PLINK_wait(plink_npu_src, channel[0].id, timeout) == PLINK_STATUS_OK)
  485. {
  486. do
  487. {
  488. sts = PLINK_recv(plink_npu_src, channel[0].id, &channel[0].pkt);
  489. int count = getBufferCount(&channel[0].pkt);
  490. if (count < 0)
  491. channel[0].exit = 1;
  492. channel[0].available_bufs += count;
  493. } while (sts == PLINK_STATUS_MORE_DATA);
  494. }
  495. }
  496. }
  497. else if (hdr->type == PLINK_TYPE_MESSAGE)
  498. {
  499. PlinkMsg *msg = (PlinkMsg *)(recvpkt.list[i]);
  500. if (msg->msg == PLINK_EXIT_CODE)
  501. {
  502. exitcode = 1;
  503. printf("Exit\n");
  504. break;
  505. }
  506. }
  507. }
  508. if (recvpkt.fd != PLINK_INVALID_FD) { // dmabuf fd
  509. if (VMEM_release(vmem, &vmem_params) != VMEM_STATUS_OK)
  510. errExit("Failed to release buffer.");
  511. close(recvpkt.fd);
  512. }
  513. frmcnt++;
  514. #if 0
  515. if (frmcnt >= frames)
  516. {
  517. msg.header.type = PLINK_TYPE_MESSAGE;
  518. msg.header.size = DATA_SIZE(PlinkMsg);
  519. msg.msg = PLINK_EXIT_CODE;
  520. sendpkt.list[0] = &msg;
  521. sendpkt.num = 1;
  522. sendpkt.fd = PLINK_INVALID_FD;
  523. if (PLINK_send(plink_npu_sink, 0, &sendpkt) == PLINK_STATUS_ERROR)
  524. errExit("Failed to send data.");
  525. break;
  526. }
  527. #endif
  528. } while (exitcode == 0);
  529. retreiveSentBuffers(plink_npu_src, &channel[0]);
  530. cleanup:
  531. sleep(1); // Sleep one second to make sure server is ready for exit
  532. PLINK_close(plink_npu_sink, 0);
  533. if (fp != NULL)
  534. fclose(fp);
  535. for (i = 0; i < input_num; i++) {
  536. shl_mem_free(input_aligned[i]);
  537. }
  538. csinn_session_deinit(sess);
  539. csinn_free_session(sess);
  540. return 0;
  541. }