aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'nodes/ti_semseg_cnn/src/semseg_cnn_manage_graph.cpp')
-rw-r--r--nodes/ti_semseg_cnn/src/semseg_cnn_manage_graph.cpp1188
1 files changed, 1188 insertions, 0 deletions
diff --git a/nodes/ti_semseg_cnn/src/semseg_cnn_manage_graph.cpp b/nodes/ti_semseg_cnn/src/semseg_cnn_manage_graph.cpp
new file mode 100644
index 0000000..7b3cca3
--- /dev/null
+++ b/nodes/ti_semseg_cnn/src/semseg_cnn_manage_graph.cpp
@@ -0,0 +1,1188 @@
1/*
2 *
3 * Copyright (c) 2021 Texas Instruments Incorporated
4 *
5 * All rights reserved not granted herein.
6 *
7 * Limited License.
8 *
9 * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
10 * license under copyrights and patents it now or hereafter owns or controls to make,
11 * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
12 * terms herein. With respect to the foregoing patent license, such license is granted
13 * solely to the extent that any such patent is necessary to Utilize the software alone.
14 * The patent license shall not apply to any combinations which include this software,
15 * other than combinations with devices manufactured by or for TI ("TI Devices").
16 * No hardware patent is licensed hereunder.
17 *
18 * Redistributions must preserve existing copyright notices and reproduce this license
19 * (including the above copyright notice and the disclaimer and (if applicable) source
20 * code license limitations below) in the documentation and/or other materials provided
21 * with the distribution
22 *
23 * Redistribution and use in binary form, without modification, are permitted provided
24 * that the following conditions are met:
25 *
26 * * No reverse engineering, decompilation, or disassembly of this software is
27 * permitted with respect to any software provided in binary form.
28 *
29 * * any redistribution and use are licensed by TI for use only with TI Devices.
30 *
31 * * Nothing shall obligate TI to provide you with source code for the software
32 * licensed and provided to you in appCntxtect code.
33 *
34 * If software source code is provided to you, modification and redistribution of the
35 * source code are permitted provided that the following conditions are met:
36 *
37 * * any redistribution and use of the source code, including any resulting derivative
38 * works, are licensed by TI for use only with TI Devices.
39 *
40 * * any redistribution and use of any appCntxtect code compiled from the source code
41 * and any resulting derivative works, are licensed by TI for use only with TI Devices.
42 *
43 * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
44 *
45 * may be used to endorse or promote products derived from this software without
46 * specific prior written permission.
47 *
48 * DISCLAIMER.
49 *
50 * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS
51 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 * IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT,
54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
55 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
57 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
58 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
59 * OF THE POSSIBILITY OF SUCH DAMAGE.
60 *
61 */
62
63#include <signal.h>
64#include <stdio.h>
65#include <stdlib.h>
66
67#include <app_ptk_demo_common.h>
68#include <cm_common.h>
69#include <cm_postproc_node_cntxt.h>
70
71#include "semseg_cnn.h"
72
73#define SEMSEG_CNN_MAX_OUT_TENSOR_DIMS (3U)
74#define SEMSEG_CNN_NUM_GRAPH_PARAMS (3U)
75
76
77
78vx_status SEMSEG_CNN_init_SS(SEMSEG_CNN_Context *appCntxt)
79{
80 int32_t i;
81 int32_t vxStatus = VX_SUCCESS;
82 vx_image scalerInput;
83 CM_LdcNodeCntxt *ldcObj;
84 CM_ScalerNodeCntxt *scalerObj;
85 CM_DLRNodeCntxt *dlrObj;
86
87 ldcObj = &appCntxt->ldcObj;
88 scalerObj = &appCntxt->scalerObj;
89 dlrObj = &appCntxt->dlrObj;
90
91
92 // Create input image object
93 if (vxStatus == (vx_status)VX_SUCCESS)
94 {
95 for (i = 0; i < appCntxt->pipelineDepth; i++)
96 {
97 // create objects
98 appCntxt->vxInputImage[i] = vxCreateImage(appCntxt->vxContext,
99 appCntxt->inputImageWidth,
100 appCntxt->inputImageHeight,
101 VX_DF_IMAGE_UYVY);
102
103 if (appCntxt->vxInputImage[i] == NULL)
104 {
105 PTK_printf("[%s:%d] vxCreateImage() failed\n",
106 __FUNCTION__, __LINE__);
107
108 vxStatus = VX_FAILURE;
109 break;
110 }
111
112 vxSetReferenceName((vx_reference)appCntxt->vxInputImage[i],
113 "InputImage");
114 }
115 }
116
117 // Create rectified image object
118 if ((vxStatus == (vx_status)VX_SUCCESS) && appCntxt->enableLdcNode)
119 {
120 for (i = 0; i < appCntxt->pipelineDepth; i++)
121 {
122 appCntxt->vxRectifiedImage[i] =
123 vxCreateImage(appCntxt->vxContext,
124 appCntxt->inputImageWidth,
125 appCntxt->inputImageHeight,
126 VX_DF_IMAGE_NV12);
127
128 if (appCntxt->vxRectifiedImage[i] == NULL)
129 {
130 PTK_printf("[%s:%d] vxCreateImage() failed\n",
131 __FUNCTION__, __LINE__);
132
133 vxStatus = VX_FAILURE;
134 break;
135 }
136
137 vxSetReferenceName((vx_reference)appCntxt->vxRectifiedImage[i],
138 "RectifiedImage_NV12");
139 }
140 }
141
142 if (vxStatus == (vx_status)VX_SUCCESS)
143 {
144 vx_size tensorDims[SEMSEG_CNN_MAX_OUT_TENSOR_DIMS];
145
146 /* DIM 0 - Width. */
147 tensorDims[0] = appCntxt->tidlImageWidth;
148
149 /* DIM 1 - Height. */
150 tensorDims[1] = appCntxt->tidlImageHeight;
151
152 /* DIM 2 - Number of channels. */
153 tensorDims[2] = 1;
154
155 for (i = 0; i < appCntxt->pipelineDepth; i++)
156 {
157 appCntxt->vxOutTensor[i] =
158 vxCreateTensor(appCntxt->vxContext,
159 SEMSEG_CNN_MAX_OUT_TENSOR_DIMS,
160 tensorDims,
161 VX_TYPE_UINT8,
162 0);
163
164 if (appCntxt->vxOutTensor[i] == NULL)
165 {
166 PTK_printf("[%s:%d] vxCreateTensor() failed\n",
167 __FUNCTION__, __LINE__);
168
169 vxStatus = VX_FAILURE;
170 break;
171 }
172 }
173 }
174
175 if (vxStatus == (vx_status)VX_SUCCESS)
176 {
177 int32_t numDims;
178
179#if 0
180 CM_DLRCreateParams params;
181 int32_t status;
182
183 params.modelPath = appCntxt->dlrModelPath;
184 params.devType = DLR_DEVTYPE_CPU;
185 params.devId = 0;
186
187 status = CM_dlrNodeCntxtInit(dlrObj, &params);
188
189 if (status < 0)
190 {
191 PTK_printf("[%s:%d] CM_dlrNodeCntxtInit() failed.\n",
192 __FUNCTION__, __LINE__);
193
194 vxStatus = VX_FAILURE;
195 }
196#endif
197
198 numDims = dlrObj->input.info[0].dim - 1;
199 if (dlrObj->input.numInfo != CM_PREPROC_NUM_OUTPUT_TENSORS)
200 {
201 PTK_printf("[%s:%d] Number of DLR inputs [%d] does not match the "
202 "number of tensors [%d] output by the pre-processing "
203 "node.\n",
204 __FUNCTION__,
205 __LINE__,
206 dlrObj->input.numInfo,
207 CM_PREPROC_NUM_OUTPUT_TENSORS);
208
209 vxStatus = VX_FAILURE;
210 }
211 else if (numDims != CM_PREPROC_OUTPUT_TENSORS_DIMS)
212 {
213 PTK_printf("[%s:%d] Number of DLR input dims [%d] does not match the "
214 "number of tensor dims [%d] output by the pre-processing "
215 "node.\n",
216 __FUNCTION__,
217 __LINE__,
218 numDims,
219 CM_PREPROC_OUTPUT_TENSORS_DIMS);
220
221 vxStatus = VX_FAILURE;
222 }
223 else
224 {
225 CM_DLRIfInfo *info;
226
227 /* Allocate DLR input buffers. Currenly, the input buffers are held
228 * for each pipelined outputs so we need pipeline number of input
229 * buffers.
230 */
231 info = &dlrObj->input.info[0];
232 for (i = 0; i < appCntxt->pipelineDepth; i++)
233 {
234 /* Allocate the input buffer. */
235 appCntxt->dlrInputBuff[i] = (float *)
236 tivxMemAlloc(info->size * sizeof(float), TIVX_MEM_EXTERNAL);
237
238 if (appCntxt->dlrInputBuff[i] == NULL)
239 {
240 PTK_printf("[%s:%d] Failed to allocate input (%d) "
241 "of size (%d) bytes.\n",
242 __FUNCTION__, __LINE__, i, info->size);
243 vxStatus = VX_FAILURE;
244 break;
245 }
246 }
247
248 /* Allocate DLR input buffer. Curently, the output buffer is not
249 * held across frames so just one istance is sufficient.
250 */
251 if (vxStatus == (vx_status)VX_SUCCESS)
252 {
253 /* Allocate the output buffer. */
254 info = &dlrObj->output.info[0];
255 for (i = 0; i < appCntxt->pipelineDepth; i++)
256 {
257 /* Allocate the input buffer. */
258 appCntxt->dlrOutputBuff[i] = (int32_t *)
259 tivxMemAlloc(info->size * sizeof(int32_t), TIVX_MEM_EXTERNAL);
260
261 if (appCntxt->dlrOutputBuff[i] == NULL)
262 {
263 PTK_printf("[%s:%d] Failed to allocate output (%d) "
264 "of size (%d) bytes.\n",
265 __FUNCTION__, __LINE__, i, info->size);
266 vxStatus = VX_FAILURE;
267 break;
268 }
269 }
270 }
271 }
272 }
273
274 /* Input image will be the scaler default input. */
275 scalerInput = appCntxt->vxInputImage[0];
276
277 /************************/
278 /* LDC node */
279 /************************/
280 if ((appCntxt->enableLdcNode) && (vxStatus == (vx_status)VX_SUCCESS))
281 {
282 CM_LdcCreateParams params;
283
284 params.width = appCntxt->inputImageWidth;
285 params.height = appCntxt->inputImageHeight;
286 params.ssFactor = appCntxt->ldcSsFactor;
287 params.blockWidth = appCntxt->ldcBlockWidth;
288 params.blockHeight = appCntxt->ldcBlockHeight;
289 params.pixelPad = appCntxt->ldcPixelPad;
290 params.lutFilePath = appCntxt->ldcLutFilePath;
291
292 vxStatus = CM_ldcNodeCntxtInit(&appCntxt->ldcObj,
293 appCntxt->vxContext,
294 &params);
295
296 if (vxStatus != (vx_status)VX_SUCCESS)
297 {
298 PTK_printf("[%s:%d] CM_ldcNodeCntxtInit() failed\n",
299 __FUNCTION__, __LINE__);
300 }
301 else
302 {
303 vxStatus = CM_ldcNodeCntxtSetup(ldcObj,
304 appCntxt->vxContext,
305 appCntxt->vxGraph,
306 appCntxt->vxInputImage[0],
307 appCntxt->vxRectifiedImage[0]);
308
309 if (vxStatus != (vx_status)VX_SUCCESS)
310 {
311 PTK_printf("[%s:%d] CM_ldcNodeCntxtSetup() failed\n",
312 __FUNCTION__, __LINE__);
313
314 vxStatus = VX_FAILURE;
315 }
316 else
317 {
318 /* LDC output will be the scaler input. */
319 scalerInput = appCntxt->vxRectifiedImage[0];
320 }
321 }
322 }
323
324 /************************/
325 /* Scaler node */
326 /************************/
327 if (vxStatus == (vx_status)VX_SUCCESS)
328 {
329 CM_ScalerCreateParams params;
330
331 params.width = appCntxt->tidlImageWidth;
332 params.height = appCntxt->tidlImageHeight;
333 params.imageType = VX_DF_IMAGE_NV12;
334 params.interpolation = VX_INTERPOLATION_BILINEAR;
335 params.pipelineDepth = appCntxt->pipelineDepth;
336
337 vxStatus = CM_scalerNodeCntxtInit(&appCntxt->scalerObj,
338 appCntxt->vxContext,
339 &params);
340
341 if (vxStatus != (vx_status)VX_SUCCESS)
342 {
343 PTK_printf("[%s:%d] CM_scalerNodeCntxtInit() failed\n",
344 __FUNCTION__, __LINE__);
345 }
346 else
347 {
348 vxStatus = CM_scalerNodeCntxtSetup(scalerObj,
349 appCntxt->vxContext,
350 appCntxt->vxGraph,
351 scalerInput);
352
353 if (vxStatus != (vx_status)VX_SUCCESS)
354 {
355 PTK_printf("[%s:%d] CM_scalerNodeCntxtSetup() failed\n",
356 __FUNCTION__, __LINE__);
357
358 vxStatus = VX_FAILURE;
359 }
360 }
361 }
362
363 return vxStatus;
364}
365
366vx_status SEMSEG_CNN_deinit_SS(SEMSEG_CNN_Context *appCntxt)
367{
368 CM_DLRNodeCntxt *dlrObj;
369 CM_DLRIfInfo *info;
370 int32_t i;
371 vx_status vxStatus = VX_SUCCESS;
372
373 dlrObj = &appCntxt->dlrObj;
374
375
376 for (i = 0; i < appCntxt->pipelineDepth; i++)
377 {
378 if (appCntxt->vxInputImage[i] != NULL)
379 {
380 vxReleaseImage(&appCntxt->vxInputImage[i]);
381 }
382 }
383
384 if (appCntxt->enableLdcNode)
385 {
386 for (i = 0; i < appCntxt->pipelineDepth; i++)
387 {
388 if (appCntxt->vxRectifiedImage[i] != NULL)
389 {
390 vxReleaseImage(&appCntxt->vxRectifiedImage[i]);
391 }
392 }
393
394 CM_ldcNodeCntxtDeInit(&appCntxt->ldcObj);
395 }
396
397
398 /* Scaler node. */
399 CM_scalerNodeCntxtDeInit(&appCntxt->scalerObj);
400
401 // vxOutTensor is always created
402 {
403 for (i = 0; i < appCntxt->pipelineDepth; i++)
404 {
405 if (appCntxt->vxOutTensor[i] != NULL)
406 {
407 vxReleaseTensor(&appCntxt->vxOutTensor[i]);
408 }
409 }
410 }
411
412 /* De-allocate the input buffer. */
413 info = &dlrObj->input.info[0];
414 for (i = 0; i < appCntxt->pipelineDepth; i++)
415 {
416 if (appCntxt->dlrInputBuff[i] != NULL)
417 {
418 tivxMemFree(appCntxt->dlrInputBuff[i],
419 info->size * sizeof(float),
420 TIVX_MEM_EXTERNAL);
421 }
422 }
423
424 /* De-allocate the DLR output buffer. */
425 info = &dlrObj->output.info[0];
426 for (i = 0; i < appCntxt->pipelineDepth; i++)
427 {
428 if (appCntxt->dlrOutputBuff[i] != NULL)
429 {
430 tivxMemFree(appCntxt->dlrOutputBuff[i],
431 info->size * sizeof(int32_t),
432 TIVX_MEM_EXTERNAL);
433 }
434 }
435
436 return vxStatus;
437}
438
439vx_status SEMSEG_CNN_setupPipeline(SEMSEG_CNN_Context * appCntxt)
440{
441 CM_LdcNodeCntxt *ldcObj;
442 CM_ScalerNodeCntxt *scalerObj;
443 SEMSEG_CNN_graphParams *paramDesc;
444 vx_graph_parameter_queue_params_t q[SEMSEG_CNN_NUM_GRAPH_PARAMS];
445
446 vx_status vxStatus;
447 uint32_t appValue;
448 uint32_t i;
449 uint32_t cnt;
450
451 ldcObj = &appCntxt->ldcObj;
452 scalerObj = &appCntxt->scalerObj;
453 cnt = 0;
454
455 appCntxt->numGraphParams = 3;
456
457 /* LDC node Param 6 ==> graph param 0. */
458 vxStatus = ptkdemo_addParamByNodeIndex(appCntxt->vxGraph,
459 ldcObj->vxNode,
460 6);
461
462 if (vxStatus != (vx_status)VX_SUCCESS)
463 {
464 PTK_printf("[%s:%d] ptkdemo_addParamByNodeIndex() failed\n",
465 __FUNCTION__, __LINE__);
466 }
467 else
468 {
469 q[cnt++].refs_list = (vx_reference*)appCntxt->vxInputImage;
470 }
471
472 if (vxStatus == (vx_status)VX_SUCCESS)
473 {
474 /* LDC node Param 7 ==> graph param 1. */
475 vxStatus = ptkdemo_addParamByNodeIndex(appCntxt->vxGraph,
476 ldcObj->vxNode,
477 7);
478
479 if (vxStatus != (vx_status)VX_SUCCESS)
480 {
481 PTK_printf("[%s:%d] ptkdemo_addParamByNodeIndex() failed\n",
482 __FUNCTION__, __LINE__);
483 }
484 else
485 {
486 q[cnt++].refs_list = (vx_reference*)appCntxt->vxRectifiedImage;
487 }
488 }
489
490 if (vxStatus == (vx_status)VX_SUCCESS)
491 {
492 /* Scaler node Param 1 ==> graph param 1/2. */
493 vxStatus = ptkdemo_addParamByNodeIndex(appCntxt->vxGraph,
494 scalerObj->vxNode,
495 1);
496
497 if (vxStatus != (vx_status)VX_SUCCESS)
498 {
499 PTK_printf("[%s:%d] ptkdemo_addParamByNodeIndex() failed\n",
500 __FUNCTION__, __LINE__);
501 }
502 else
503 {
504 q[cnt++].refs_list = (vx_reference*)scalerObj->outImage;
505 }
506 }
507
508 if (vxStatus == (vx_status)VX_SUCCESS)
509 {
510 for (i = 0; i < cnt; i++)
511 {
512 q[i].graph_parameter_index = i;
513 q[i].refs_list_size = appCntxt->pipelineDepth;
514 }
515
516 // allocate free Q
517 for (i = 0; i < appCntxt->pipelineDepth; i++)
518 {
519 paramDesc = &appCntxt->paramDesc[i];
520 paramDesc->vxInputImage = appCntxt->vxInputImage[i];
521 paramDesc->vxOutTensor = appCntxt->vxOutTensor[i];
522 paramDesc->timestamp = &appCntxt->timestamp[i];
523 paramDesc->dlrInputBuff = appCntxt->dlrInputBuff[i];
524 paramDesc->dlrOutputBuff = appCntxt->dlrOutputBuff[i];
525 paramDesc->vxScalerOut = scalerObj->outImage[i];
526 paramDesc->vxRectifiedImage = appCntxt->vxRectifiedImage[i];
527
528 SEMSEG_CNN_enqueInputDesc(appCntxt, paramDesc);
529 }
530
531 vxStatus = vxSetGraphScheduleConfig(appCntxt->vxGraph,
532 VX_GRAPH_SCHEDULE_MODE_QUEUE_AUTO,
533 cnt,
534 q);
535
536 if (vxStatus != (vx_status)VX_SUCCESS)
537 {
538 PTK_printf("[%s:%d] vxSetGraphScheduleConfig() failed\n",
539 __FUNCTION__, __LINE__);
540 }
541 }
542
543 if (vxStatus == VX_SUCCESS)
544 {
545 /* explicitly set graph pipeline depth */
546 vxStatus = tivxSetGraphPipelineDepth(appCntxt->vxGraph,
547 appCntxt->pipelineDepth);
548
549 if (vxStatus != VX_SUCCESS)
550 {
551 PTK_printf("[%s:%d] tivxSetGraphPipelineDepth() failed\n",
552 __FUNCTION__, __LINE__);
553 }
554 }
555
556 if (vxStatus == VX_SUCCESS)
557 {
558 appValue = appCntxt->vxEvtAppValBase + SEMSEG_CNN_SCALER_NODE_COMPLETE_EVENT;
559
560 vxStatus = vxRegisterEvent((vx_reference)scalerObj->vxNode,
561 VX_EVENT_NODE_COMPLETED,
562 0,
563 appValue);
564
565 if (vxStatus != (vx_status)VX_SUCCESS)
566 {
567 PTK_printf("[%s:%d] vxRegisterEvent() failed\n",
568 __FUNCTION__, __LINE__);
569 }
570 }
571
572
573 return vxStatus;
574}
575
576
577void SEMSEG_CNN_printStats(SEMSEG_CNN_Context * appCntxt)
578{
579 tivx_utils_graph_perf_print(appCntxt->vxGraph);
580
581 appPerfPointPrint(&appCntxt->semsegPerf);
582 PTK_printf("\n");
583 appPerfPointPrintFPS(&appCntxt->semsegPerf);
584 PTK_printf("\n");
585}
586
587
588vx_status SEMSEG_CNN_exportStats(SEMSEG_CNN_Context * appCntxt, FILE *fp, bool exportAll)
589{
590 vx_status vxStatus = tivx_utils_graph_perf_export(fp, appCntxt->vxGraph);
591
592 if (vxStatus != (vx_status)VX_SUCCESS)
593 {
594 PTK_printf("[%s:%d] tivx_utils_graph_perf_export() failed\n",
595 __FUNCTION__, __LINE__);
596 }
597
598 if (vxStatus == (vx_status)VX_SUCCESS)
599 {
600 if (exportAll == true)
601 {
602 app_perf_point_t *perfArr[1] = {&appCntxt->semsegPerf};
603 appPerfStatsExportAll(fp, perfArr, 1);
604 }
605 }
606
607 return vxStatus;
608}
609
610
611vx_status SEMSEG_CNN_waitGraph(SEMSEG_CNN_Context * appCntxt)
612{
613 vx_status vxStatus;
614
615 vxStatus = vxWaitGraph(appCntxt->vxGraph);
616
617 if (vxStatus != (vx_status)VX_SUCCESS)
618 {
619 PTK_printf("[%s:%d] vxWaitGraph() failed\n",
620 __FUNCTION__, __LINE__);
621
622 vxStatus = VX_FAILURE;
623 }
624
625 if (vxStatus == (vx_status)VX_SUCCESS)
626 {
627 /* Wait for the output queue to get flushed. */
628 while (appCntxt->freeQ.size() != appCntxt->pipelineDepth)
629 {
630 std::this_thread::sleep_for(std::chrono::milliseconds(50));
631 }
632 }
633
634 return vxStatus;
635}
636
637
638vx_status SEMSEG_CNN_process(SEMSEG_CNN_Context * appCntxt,
639 SEMSEG_CNN_graphParams * gpDesc,
640 uint64_t timestamp)
641{
642 vx_status vxStatus = VX_SUCCESS;
643 uint16_t i;
644 uint8_t cnt = 0;
645
646 vx_reference obj[SEMSEG_CNN_NUM_GRAPH_PARAMS];
647
648 // set timestamp of input image
649 *gpDesc->timestamp = timestamp;
650
651 obj[cnt++] = (vx_reference)gpDesc->vxInputImage;
652 if (appCntxt->enableLdcNode)
653 {
654 obj[cnt++] = (vx_reference)gpDesc->vxRectifiedImage;
655 }
656 obj[cnt++] = (vx_reference)gpDesc->vxScalerOut;
657
658 // Enqueue buffers
659 // Enqueue vxOutTensor after DLR is completed
660 for (i = 0; i < appCntxt->numGraphParams; i++)
661 {
662 vxStatus = vxGraphParameterEnqueueReadyRef(appCntxt->vxGraph,
663 i,
664 &obj[i],
665 1);
666 if (vxStatus != (vx_status)VX_SUCCESS)
667 {
668 PTK_printf("[%s:%d] vxGraphParameterEnqueueReadyRef(%d) "
669 "failed\n", __FUNCTION__, __LINE__, i);
670 break;
671 }
672 }
673
674 /* Push the descriptor to the DLR input queue. */
675 SEMSEG_CNN_enquePreprocInputDesc(appCntxt, gpDesc);
676
677 return vxStatus;
678}
679
680
681vx_status SEMSEG_CNN_preProcess(SEMSEG_CNN_Context * appCntxt,
682 vx_image vxScalerOut,
683 float * dlrInputBuff)
684{
685 vx_rectangle_t rect;
686 vx_imagepatch_addressing_t imgAddr;
687 uint8_t *srcPtr[2];
688 vx_map_id mapId[2];
689 bool mapped[2] = {false, false};
690 vx_status vxStatus;
691
692 rect.start_x = 0;
693 rect.start_y = 0;
694 rect.end_x = appCntxt->tidlImageWidth;
695 rect.end_y = appCntxt->tidlImageHeight;
696
697 /* Map the image planes. */
698 for (uint32_t i = 0; i < 2; i++)
699 {
700 /* Get the pointer to the YUV data plans. */
701 vxStatus = vxMapImagePatch(vxScalerOut,
702 &rect,
703 i,
704 &mapId[i],
705 &imgAddr,
706 (void **)&srcPtr[i],
707 VX_WRITE_ONLY,
708 VX_MEMORY_TYPE_HOST,
709 VX_NOGAP_X);
710
711 if (vxStatus != (vx_status)VX_SUCCESS)
712 {
713 PTK_printf("[%s:%d] vxMapImagePatch() failed.",
714 __FUNCTION__, __LINE__);
715 }
716 else
717 {
718 mapped[i] = true;
719 }
720
721 /* UV plane has half the height. */
722 rect.end_y /= 2;
723 }
724
725 /* Take thr output image from the scaler which is in NV12 format and do
726 * the following:
727 * - Color convert the image from YUV420 to BGR format
728 * - Convert to float and write to the DLR input buffer
729 */
730
731 if (vxStatus == (vx_status)VX_SUCCESS)
732 {
733 vxStatus =
734 CM_SEMSEG_CNN_convertYUV2RGB(dlrInputBuff,
735 (const uint8_t**)srcPtr,
736 appCntxt->preProcMean,
737 appCntxt->preProcScale,
738 appCntxt->tidlImageWidth,
739 appCntxt->tidlImageHeight);
740
741 if (vxStatus != (vx_status)VX_SUCCESS)
742 {
743 PTK_printf("[%s:%d] CM_SEMSEG_CNN_convertYUV2RGB() failed.",
744 __FUNCTION__, __LINE__);
745 }
746 }
747
748 /* Unmap the image planes. */
749 for (uint32_t i = 0; i < 2; i++)
750 {
751 if (mapped[i] == true)
752 {
753 vxUnmapImagePatch(vxScalerOut, mapId[i]);
754 }
755 }
756
757 return vxStatus;
758}
759
760vx_status SEMSEG_CNN_postProcess(SEMSEG_CNN_Context * appCntxt,
761 vx_image vxScalerOut,
762 int32_t * dlrOutputBuff)
763{
764 vx_rectangle_t rect;
765 vx_imagepatch_addressing_t imgAddr;
766 vx_map_id mapId;
767 uint8_t *dPtr;
768 vx_status vxStatus;
769
770 /* Get the pointer to the UV plane in the output image. */
771 rect.start_x = 0;
772 rect.start_y = 0;
773 rect.end_x = appCntxt->tidlImageWidth;
774 rect.end_y = appCntxt->tidlImageHeight/2; // Chroma is UV interleaved
775
776 /* Get the pointer to the UV data plans. */
777 vxStatus = vxMapImagePatch(vxScalerOut,
778 &rect,
779 1, // UV plane
780 &mapId,
781 &imgAddr,
782 (void **)&dPtr,
783 VX_WRITE_ONLY,
784 VX_MEMORY_TYPE_HOST,
785 VX_NOGAP_X);
786
787 if (vxStatus != (vx_status)VX_SUCCESS)
788 {
789 PTK_printf("[%s:%d] vxMapImagePatch() failed.",
790 __FUNCTION__, __LINE__);
791 }
792 else
793 {
794 int32_t *classId;
795 uint8_t *p;
796 float alpha;
797 float alphaC;
798 int32_t widthInByte;
799
800 alpha = 0.5;
801 alphaC = 1.0f - alpha;
802
803 classId = dlrOutputBuff;
804 widthInByte = imgAddr.dim_x/2;
805
806 /* Blend the input image data with the DLR output tensor and generate
807 * the output image.
808 */
809 for (uint32_t i = 0; i < imgAddr.dim_y; i++)
810 {
811 p = dPtr;
812
813 for (int32_t j = 0; j < widthInByte; j++)
814 {
815 uint8_t c = (uint8_t)*classId;
816
817 p[0] = (uint8_t)((p[0] * alpha) + yuvColMap[c].u * alphaC);
818 p[1] = (uint8_t)((p[1] * alpha) + yuvColMap[c].v * alphaC);
819
820 /* Move to the next pain of UV pixels. */
821 p += 2;
822
823 /* We use one class Id for a pair of UV pixels, so skip one
824 * class value.
825 */
826 classId += 2;
827 }
828
829 /* Move to the next line in the image. */
830 dPtr += imgAddr.stride_y;
831
832 /* Skip the next line in the tensor data. */
833 classId += appCntxt->tidlImageWidth;
834 }
835
836 vxUnmapImagePatch(vxScalerOut, mapId);
837 }
838
839 return vxStatus;
840
841}
842
843vx_status SEMSEG_CNN_createOutTensor(SEMSEG_CNN_Context * appCntxt,
844 vx_tensor vxOutTensor,
845 int32_t * dlrOutputBuff)
846{
847 uint8_t *dPtr;
848 vx_size start[SEMSEG_CNN_MAX_OUT_TENSOR_DIMS];
849 vx_size strides[SEMSEG_CNN_MAX_OUT_TENSOR_DIMS];
850 vx_size tensorDims[SEMSEG_CNN_MAX_OUT_TENSOR_DIMS];
851 vx_map_id mapId;
852 vx_status vxStatus;
853
854 start[0] = 0;
855 start[1] = 0;
856 start[2] = 0;
857
858 /* DIM 0 - Width. */
859 tensorDims[0] = appCntxt->tidlImageWidth;
860
861 /* DIM 1 - Height. */
862 tensorDims[1] = appCntxt->tidlImageHeight;
863
864 /* DIM 2 - Number of channels. */
865 tensorDims[2] = 1;
866
867 /* Strides */
868 strides[0] = 1;
869 strides[1] = tensorDims[0];
870 strides[2] = strides[1]*tensorDims[1];
871
872 vxStatus = tivxMapTensorPatch(vxOutTensor,
873 SEMSEG_CNN_MAX_OUT_TENSOR_DIMS,
874 start,
875 tensorDims,
876 &mapId,
877 strides,
878 (void **)&dPtr,
879 VX_READ_AND_WRITE,
880 VX_MEMORY_TYPE_HOST);
881
882 if (vxStatus != (vx_status)VX_SUCCESS)
883 {
884 PTK_printf("[%s:%d] tivxMapTensorPatch() failed.",
885 __FUNCTION__, __LINE__);
886 }
887 else
888 {
889 int32_t *sPtr;
890 uint32_t size;
891
892 sPtr = dlrOutputBuff;
893 size = tensorDims[0] * tensorDims[1];
894
895 for (uint32_t i = 0; i < size; i++)
896 {
897 *dPtr++ = (uint8_t)*sPtr++;
898 }
899
900 vxStatus = tivxUnmapTensorPatch(vxOutTensor, mapId);
901
902 if (vxStatus != (vx_status)VX_SUCCESS)
903 {
904 PTK_printf("[%s:%d] tivxUnmapTensorPatch() failed.",
905 __FUNCTION__, __LINE__);
906 }
907 }
908
909 return vxStatus;
910}
911
912
913
914vx_status SEMSEG_CNN_popFreeInputDesc(SEMSEG_CNN_Context *appCntxt,
915 SEMSEG_CNN_graphParams **gpDesc)
916{
917 vx_status vxStatus = VX_SUCCESS;
918
919 *gpDesc = appCntxt->freeQ.pop();
920
921 if (*gpDesc == nullptr)
922 {
923 vxStatus = VX_FAILURE;
924 }
925
926 return vxStatus;
927}
928
929
930vx_status SEMSEG_CNN_popPreprocInputDesc(SEMSEG_CNN_Context *appCntxt,
931 SEMSEG_CNN_graphParams **gpDesc)
932{
933 vx_status vxStatus = VX_SUCCESS;
934
935 *gpDesc = appCntxt->preProcQ.pop();
936
937 if (*gpDesc == nullptr)
938 {
939 vxStatus = VX_FAILURE;
940 }
941
942 return vxStatus;
943}
944
945
946vx_status SEMSEG_CNN_popDLRInputDesc(SEMSEG_CNN_Context *appCntxt,
947 SEMSEG_CNN_graphParams **gpDesc)
948{
949 vx_status vxStatus = VX_SUCCESS;
950
951 *gpDesc = appCntxt->dlrQ.pop();
952
953 if (*gpDesc == nullptr)
954 {
955 vxStatus = VX_FAILURE;
956 }
957
958 return vxStatus;
959}
960
961vx_status SEMSEG_CNN_popPostprocInputDesc(SEMSEG_CNN_Context *appCntxt,
962 SEMSEG_CNN_graphParams **gpDesc)
963{
964 vx_status vxStatus = VX_SUCCESS;
965
966 *gpDesc = appCntxt->postProcQ.pop();
967
968 if (*gpDesc == nullptr)
969 {
970 vxStatus = VX_FAILURE;
971 }
972
973 return vxStatus;
974}
975
976vx_status SEMSEG_CNN_getOutputDesc(SEMSEG_CNN_Context *appCntxt,
977 SEMSEG_CNN_graphParams *gpDesc)
978{
979 SEMSEG_CNN_graphParams *desc;
980 vx_status vxStatus = VX_SUCCESS;
981
982 desc = appCntxt->outputQ.peek();
983
984 if (desc == nullptr)
985 {
986 vxStatus = VX_FAILURE;
987 }
988 else
989 {
990 *gpDesc = *desc;
991 }
992
993 return vxStatus;
994}
995
996vx_status SEMSEG_CNN_popOutputDesc(SEMSEG_CNN_Context *appCntxt,
997 SEMSEG_CNN_graphParams **gpDesc)
998{
999 vx_status vxStatus = VX_SUCCESS;
1000
1001 *gpDesc = appCntxt->outputQ.pop();
1002
1003 if (*gpDesc == nullptr)
1004 {
1005 vxStatus = VX_FAILURE;
1006 }
1007
1008 return vxStatus;
1009}
1010
1011
1012void SEMSEG_CNN_enqueInputDesc(SEMSEG_CNN_Context *appCntxt,
1013 SEMSEG_CNN_graphParams *desc)
1014{
1015 appCntxt->freeQ.push(desc);
1016}
1017
1018
1019void SEMSEG_CNN_enquePreprocInputDesc(SEMSEG_CNN_Context *appCntxt,
1020 SEMSEG_CNN_graphParams *desc)
1021{
1022 appCntxt->preProcQ.push(desc);
1023}
1024
1025void SEMSEG_CNN_enqueDLRInputDesc(SEMSEG_CNN_Context *appCntxt,
1026 SEMSEG_CNN_graphParams *desc)
1027{
1028 appCntxt->dlrQ.push(desc);
1029}
1030
1031void SEMSEG_CNN_enquePostprocInputDesc(SEMSEG_CNN_Context *appCntxt,
1032 SEMSEG_CNN_graphParams *desc)
1033{
1034 appCntxt->postProcQ.push(desc);
1035}
1036
1037
1038void SEMSEG_CNN_enqueOutputDesc(SEMSEG_CNN_Context *appCntxt,
1039 SEMSEG_CNN_graphParams *desc)
1040{
1041 appCntxt->outputQ.push(desc);
1042}
1043
1044
1045vx_status SEMSEG_CNN_processEvent(SEMSEG_CNN_Context * appCntxt, vx_event_t * event)
1046{
1047 vx_reference ref;
1048 uint8_t i;
1049 uint32_t numRefs;
1050 uint32_t index;
1051 vx_status vxStatus;
1052
1053 // For profiling
1054 float diff;
1055
1056 ref = NULL;
1057 vxStatus = (vx_status)VX_SUCCESS;
1058
1059 if(event->type == VX_EVENT_NODE_COMPLETED)
1060 {
1061 uint32_t appValue = appCntxt->vxEvtAppValBase +
1062 SEMSEG_CNN_SCALER_NODE_COMPLETE_EVENT;
1063
1064 if (event->app_value != appValue)
1065 {
1066 /* Something wrong. We did not register for this event. */
1067 PTK_printf("[%s:%d] Unknown App Value [%d].\n",
1068 __FUNCTION__, __LINE__, event->app_value);
1069
1070 vxStatus = VX_FAILURE;
1071 }
1072
1073 if (vxStatus == (vx_status)VX_SUCCESS)
1074 {
1075 if (appCntxt->startPerfCapt == false)
1076 {
1077 appCntxt->startPerfCapt = true;
1078 }
1079 else
1080 {
1081 appPerfPointEnd(&appCntxt->semsegPerf);
1082
1083 appCntxt->profileEnd = GET_TIME();
1084 diff = GET_DIFF(appCntxt->profileStart, appCntxt->profileEnd);
1085 CM_reportProctime("Inter_frame_interval", diff);
1086 }
1087
1088 appPerfPointBegin(&appCntxt->semsegPerf);
1089 appCntxt->profileStart = GET_TIME();
1090
1091 /* Node execution is complete. Deque all the parameters
1092 * for this node.
1093 */
1094 for (i = 0; i < appCntxt->numGraphParams; i++)
1095 {
1096 vxStatus = vxGraphParameterDequeueDoneRef(appCntxt->vxGraph,
1097 i,
1098 &ref,
1099 1,
1100 &numRefs);
1101 if (vxStatus != (vx_status)VX_SUCCESS)
1102 {
1103 PTK_printf("[%s:%d] vxGraphParameterDequeueDoneRef() failed\n",
1104 __FUNCTION__, __LINE__);
1105
1106 break;
1107 }
1108 }
1109
1110 }
1111
1112 if (vxStatus == (vx_status)VX_SUCCESS)
1113 {
1114 /* Wakeup the pre-process thread. The pre-process thread will
1115 * process the descriptor at the head of the queue.
1116 */
1117 appCntxt->preProcSem->notify();
1118 }
1119 }
1120
1121
1122
1123 return vxStatus;
1124}
1125
1126
1127vx_status SEMSEG_CNN_getOutBuff(SEMSEG_CNN_Context * appCntxt,
1128 vx_image * inputImage,
1129 vx_reference * output,
1130 vx_uint64 * timestamp)
1131{
1132 vx_status vxStatus;
1133 SEMSEG_CNN_graphParams desc;
1134
1135 vxStatus = SEMSEG_CNN_getOutputDesc(appCntxt, &desc);
1136
1137 if (vxStatus == (vx_status)VX_SUCCESS)
1138 {
1139
1140 if (vxStatus == (vx_status)VX_SUCCESS)
1141 {
1142 if (appCntxt->enableLdcNode)
1143 {
1144 *inputImage = desc.vxRectifiedImage;
1145 }
1146 else
1147 {
1148 *inputImage = desc.vxInputImage;
1149 }
1150
1151 if (appCntxt->enablePostProcNode)
1152 {
1153 *output = (vx_reference)desc.vxScalerOut;
1154 }
1155 else
1156 {
1157 *output = (vx_reference)desc.vxOutTensor;
1158 }
1159
1160 *timestamp = *desc.timestamp;
1161 }
1162 else
1163 {
1164 PTK_printf("[%s:%d] SEMSEG_CNN_getOutputDesc() failed\n",
1165 __FUNCTION__, __LINE__);
1166 }
1167 }
1168
1169 return vxStatus;
1170
1171}
1172
1173vx_status SEMSEG_CNN_releaseOutBuff(SEMSEG_CNN_Context * appCntxt)
1174{
1175 vx_status vxStatus;
1176 SEMSEG_CNN_graphParams * desc;
1177
1178 /* Pop the output descriptor. */
1179 vxStatus = SEMSEG_CNN_popOutputDesc(appCntxt, &desc);
1180
1181 if (vxStatus == (vx_status)VX_SUCCESS)
1182 {
1183 /* Enqueue the descriptor to the free descriptor queue. */
1184 SEMSEG_CNN_enqueInputDesc(appCntxt, desc);
1185 }
1186
1187 return vxStatus;
1188}