1 /*
2 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <sys/mman.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <semaphore.h>
26 #include <pthread.h>
27 #include <math.h>
28
29 #include "sample_comm_ive.h"
30
31 #define SAMPLE_IVE_CANNY_HYS_EDGE_HIGH_THR 150
32 #define SAMPLE_IVE_CANNY_HYS_EDGE_LOW_THR 50
33 #define SAMPLE_IVE_CANNY_THR_U16_HIGH_THR 100
34 #define SAMPLE_IVE_CANNY_THR_U16_LOW_THR 100
35 #define SAMPLE_IVE_CANNY_THR_U16_MAX_VAL 255
36 #define SAMPLE_IVE_CANNY_THR_U16_MID_VAL 0
37 #define SAMPLE_IVE_CANNY_THR_U16_MIN_VAL 0
38
39 typedef struct hiSAMPLE_IVE_CANNY_INFO_S {
40 IVE_SRC_IMAGE_S stSrc;
41 IVE_DST_IMAGE_S stEdge;
42 IVE_DST_IMAGE_S stMag;
43 IVE_MEM_INFO_S stStack;
44 IVE_CANNY_HYS_EDGE_CTRL_S stCannyHysEdgeCtrl;
45 IVE_MAG_AND_ANG_CTRL_S stMagAndAngCtrl;
46 IVE_THRESH_U16_CTRL_S stThrU16Ctrl;
47 FILE *pFpSrc;
48 FILE *pFpDst;
49 } SAMPLE_IVE_CANNY_INFO_S;
50
51 static SAMPLE_IVE_CANNY_INFO_S s_stCannyInfo;
52 static HI_BOOL s_bStopSignal = HI_FALSE;
53
SAMPLE_IVE_Canny_Uninit(SAMPLE_IVE_CANNY_INFO_S * pstCannyInfo)54 static HI_VOID SAMPLE_IVE_Canny_Uninit(SAMPLE_IVE_CANNY_INFO_S *pstCannyInfo)
55 {
56 IVE_MMZ_FREE(pstCannyInfo->stSrc.au64PhyAddr[0], pstCannyInfo->stSrc.au64VirAddr[0]);
57 IVE_MMZ_FREE(pstCannyInfo->stEdge.au64PhyAddr[0], pstCannyInfo->stEdge.au64VirAddr[0]);
58 IVE_MMZ_FREE(pstCannyInfo->stMag.au64PhyAddr[0], pstCannyInfo->stMag.au64VirAddr[0]);
59 IVE_MMZ_FREE(pstCannyInfo->stStack.u64PhyAddr, pstCannyInfo->stStack.u64VirAddr);
60 IVE_MMZ_FREE(pstCannyInfo->stCannyHysEdgeCtrl.stMem.u64PhyAddr, pstCannyInfo->stCannyHysEdgeCtrl.stMem.u64VirAddr);
61
62 IVE_CLOSE_FILE(pstCannyInfo->pFpSrc);
63 IVE_CLOSE_FILE(pstCannyInfo->pFpDst);
64 }
65
SAMPLE_IVE_Canny_Init(SAMPLE_IVE_CANNY_INFO_S * pstCannyInfo,HI_CHAR * pchSrcFileName,HI_CHAR * pchDstFileName,HI_U32 u32Width,HI_U32 u32Height)66 static HI_S32 SAMPLE_IVE_Canny_Init(SAMPLE_IVE_CANNY_INFO_S *pstCannyInfo, HI_CHAR *pchSrcFileName,
67 HI_CHAR *pchDstFileName, HI_U32 u32Width, HI_U32 u32Height)
68 {
69 HI_S32 s32Ret = HI_SUCCESS;
70 HI_U32 u32Size;
71 /* canny filter mask 5x5 */
72 HI_S8 as8Mask[IVE_MASK_NUM_25] = {
73 0, 0, 0, 0, 0,
74 0, -1, 0, 1, 0,
75 0, -2, 0, 2, 0,
76 0, -1, 0, 1, 0,
77 0, 0, 0, 0, 0};
78
79 (HI_VOID)memset_s(pstCannyInfo, sizeof(SAMPLE_IVE_CANNY_INFO_S), 0, sizeof(SAMPLE_IVE_CANNY_INFO_S));
80 (HI_VOID)memcpy_s(pstCannyInfo->stCannyHysEdgeCtrl.as8Mask, IVE_MASK_NUM_25, as8Mask, IVE_MASK_NUM_25);
81 (HI_VOID)memcpy_s(pstCannyInfo->stMagAndAngCtrl.as8Mask, IVE_MASK_NUM_25, as8Mask, IVE_MASK_NUM_25);
82 pstCannyInfo->stCannyHysEdgeCtrl.u16HighThr = SAMPLE_IVE_CANNY_HYS_EDGE_HIGH_THR;
83 pstCannyInfo->stCannyHysEdgeCtrl.u16LowThr = SAMPLE_IVE_CANNY_HYS_EDGE_LOW_THR;
84 pstCannyInfo->stMagAndAngCtrl.enOutCtrl = IVE_MAG_AND_ANG_OUT_CTRL_MAG;
85 pstCannyInfo->stMagAndAngCtrl.u16Thr = 0;
86 pstCannyInfo->stThrU16Ctrl.enMode = IVE_THRESH_U16_MODE_U16_TO_U8_MIN_MID_MAX;
87 pstCannyInfo->stThrU16Ctrl.u16HighThr = SAMPLE_IVE_CANNY_THR_U16_HIGH_THR;
88 pstCannyInfo->stThrU16Ctrl.u16LowThr = SAMPLE_IVE_CANNY_THR_U16_LOW_THR;
89 pstCannyInfo->stThrU16Ctrl.u8MaxVal = SAMPLE_IVE_CANNY_THR_U16_MAX_VAL;
90 pstCannyInfo->stThrU16Ctrl.u8MidVal = SAMPLE_IVE_CANNY_THR_U16_MID_VAL;
91 pstCannyInfo->stThrU16Ctrl.u8MinVal = SAMPLE_IVE_CANNY_THR_U16_MIN_VAL;
92
93 s32Ret = SAMPLE_COMM_IVE_CreateImage(&pstCannyInfo->stSrc, IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
94 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, CANNY_INIT_FAIL, "Error(%#x),Create Src Image failed!\n", s32Ret);
95 s32Ret = SAMPLE_COMM_IVE_CreateImage(&pstCannyInfo->stEdge, IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
96 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, CANNY_INIT_FAIL, "Error(%#x),Create edge Image failed!\n", s32Ret);
97 s32Ret = SAMPLE_COMM_IVE_CreateImage(&pstCannyInfo->stMag, IVE_IMAGE_TYPE_U16C1, u32Width, u32Height);
98 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, CANNY_INIT_FAIL, "Error(%#x),Create Mag Image failed!\n", s32Ret);
99 u32Size = (HI_U32)sizeof(HI_U16) + (HI_U32)sizeof(HI_U16);
100 u32Size = pstCannyInfo->stSrc.au32Stride[0] * pstCannyInfo->stSrc.u32Height * u32Size +
101 sizeof(IVE_CANNY_STACK_SIZE_S);
102 s32Ret = SAMPLE_COMM_IVE_CreateMemInfo(&pstCannyInfo->stStack, u32Size);
103 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, CANNY_INIT_FAIL, "Error(%#x),Create Stack Mem info failed!\n", s32Ret);
104 u32Size = (HI_U32)sizeof(HI_U16) + (HI_U32)sizeof(HI_U8);
105 u32Size = pstCannyInfo->stSrc.au32Stride[0] * pstCannyInfo->stSrc.u32Height * u32Size;
106 s32Ret = SAMPLE_COMM_IVE_CreateMemInfo(&pstCannyInfo->stCannyHysEdgeCtrl.stMem, u32Size);
107 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, CANNY_INIT_FAIL,
108 "Error(%#x),Create CannyHysEdgeCtrl.stMem Mem info failed!\n", s32Ret);
109
110 s32Ret = HI_FAILURE;
111 pstCannyInfo->pFpSrc = fopen(pchSrcFileName, "rb");
112 SAMPLE_CHECK_EXPR_GOTO(pstCannyInfo->pFpSrc == HI_NULL, CANNY_INIT_FAIL, "Error,Open file %s failed!\n",
113 pchSrcFileName);
114 pstCannyInfo->pFpDst = fopen(pchDstFileName, "wb");
115 SAMPLE_CHECK_EXPR_GOTO(pstCannyInfo->pFpDst == HI_NULL, CANNY_INIT_FAIL, "Error,Open file %s failed!\n",
116 pchDstFileName);
117
118 s32Ret = HI_SUCCESS;
119
120 CANNY_INIT_FAIL:
121 if (s32Ret != HI_SUCCESS) {
122 SAMPLE_IVE_Canny_Uninit(pstCannyInfo);
123 }
124 return s32Ret;
125 }
126
SAMPLE_IVE_Complete_Canny(SAMPLE_IVE_CANNY_INFO_S * pstCannyInfo)127 static HI_S32 SAMPLE_IVE_Complete_Canny(SAMPLE_IVE_CANNY_INFO_S *pstCannyInfo)
128 {
129 HI_S32 s32Ret = HI_SUCCESS;
130 HI_BOOL bInstant = HI_TRUE;
131 HI_BOOL bBlock = HI_TRUE;
132 HI_BOOL bFinish = HI_FALSE;
133 IVE_HANDLE IveHandle;
134
135 s32Ret = SAMPLE_COMM_IVE_ReadFile(&(pstCannyInfo->stSrc), pstCannyInfo->pFpSrc);
136 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),Read src file failed!\n", s32Ret);
137
138 s32Ret = HI_MPI_IVE_CannyHysEdge(&IveHandle, &pstCannyInfo->stSrc, &pstCannyInfo->stEdge, &pstCannyInfo->stStack,
139 &pstCannyInfo->stCannyHysEdgeCtrl, bInstant);
140 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_CannyHysEdge failed!\n", s32Ret);
141
142 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
143 while (s32Ret == HI_ERR_IVE_QUERY_TIMEOUT) {
144 usleep(IVE_QUERY_SLEEP_TIME);
145 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
146 }
147 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Query failed!\n", s32Ret);
148 s32Ret = HI_MPI_IVE_CannyEdge(&pstCannyInfo->stEdge, &pstCannyInfo->stStack);
149 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_CannyEdge failed!\n", s32Ret);
150 s32Ret = SAMPLE_COMM_IVE_WriteFile(&pstCannyInfo->stEdge, pstCannyInfo->pFpDst);
151 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),Write edge file failed!\n", s32Ret);
152
153 return s32Ret;
154 }
155
SAMPLE_IVE_Part_Canny(SAMPLE_IVE_CANNY_INFO_S * pstCannyInfo)156 static HI_S32 SAMPLE_IVE_Part_Canny(SAMPLE_IVE_CANNY_INFO_S *pstCannyInfo)
157 {
158 HI_S32 s32Ret = HI_SUCCESS;
159 HI_BOOL bInstant = HI_TRUE;
160 HI_BOOL bBlock = HI_TRUE;
161 HI_BOOL bFinish = HI_FALSE;
162 IVE_HANDLE IveHandle;
163
164 s32Ret = SAMPLE_COMM_IVE_ReadFile(&pstCannyInfo->stSrc, pstCannyInfo->pFpSrc);
165 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),Read src file failed!\n", s32Ret);
166
167 bInstant = HI_FALSE;
168 s32Ret = HI_MPI_IVE_MagAndAng(&IveHandle, &pstCannyInfo->stSrc, &pstCannyInfo->stMag, HI_NULL,
169 &pstCannyInfo->stMagAndAngCtrl, bInstant);
170 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_MagAndAng failed!\n", s32Ret);
171
172 bInstant = HI_TRUE;
173 s32Ret = HI_MPI_IVE_Thresh_U16(&IveHandle, &pstCannyInfo->stMag, &pstCannyInfo->stEdge, &pstCannyInfo->stThrU16Ctrl,
174 bInstant);
175 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Thresh_U16 failed!\n", s32Ret);
176
177 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
178 while (s32Ret == HI_ERR_IVE_QUERY_TIMEOUT) {
179 usleep(IVE_QUERY_SLEEP_TIME);
180 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
181 }
182 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Query failed!\n", s32Ret);
183
184 s32Ret = SAMPLE_COMM_IVE_WriteFile(&pstCannyInfo->stEdge, pstCannyInfo->pFpDst);
185 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),Write edge file failed!\n", s32Ret);
186
187 return s32Ret;
188 }
189
SAMPLE_IVE_CannyStop(HI_VOID)190 static HI_VOID SAMPLE_IVE_CannyStop(HI_VOID)
191 {
192 SAMPLE_IVE_Canny_Uninit(&s_stCannyInfo);
193 (HI_VOID)memset_s(&s_stCannyInfo, sizeof(s_stCannyInfo), 0, sizeof(s_stCannyInfo));
194 SAMPLE_COMM_IVE_IveMpiExit();
195 printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
196 }
197
SAMPLE_IVE_Canny(HI_CHAR chComplete)198 HI_VOID SAMPLE_IVE_Canny(HI_CHAR chComplete)
199 {
200 HI_U16 u32Width = IVE_D1_WIDTH;
201 HI_U16 u32Height = IVE_D1_HEIGHT;
202 HI_CHAR *pchSrcFileName = "./data/input/canny/canny.yuv";
203 HI_CHAR *pchDstFileName = "./data/output/canny";
204
205 HI_CHAR achSrcFileName[PATH_MAX] = {0};
206 HI_CHAR achDstFileName[PATH_MAX] = {0};
207 HI_CHAR tmpFile[PATH_MAX] = {0};
208 HI_S32 s32Ret;
209 s_bStopSignal = HI_FALSE;
210
211 SAMPLE_CHECK_EXPR_RET_VOID((strlen(pchSrcFileName) > PATH_MAX) ||
212 (realpath(pchSrcFileName, achSrcFileName) == NULL),
213 "invalid input file\n");
214
215 SAMPLE_CHECK_EXPR_RET_VOID((strlen(pchDstFileName) > PATH_MAX) ||
216 (realpath(pchDstFileName, achDstFileName) == NULL),
217 "invalid input file\n");
218
219 s32Ret = snprintf_s(tmpFile, sizeof(tmpFile), sizeof(tmpFile) - 1, "/cannyout_complete_%c.yuv", chComplete);
220 SAMPLE_CHECK_EXPR_RET_VOID(s32Ret < 0, "invalid param!\n");
221
222 s32Ret = strcat_s(achDstFileName, PATH_MAX, tmpFile);
223 SAMPLE_CHECK_EXPR_RET_VOID(s32Ret < 0, "invalid param!\n");
224
225 (HI_VOID)memset_s(&s_stCannyInfo, sizeof(s_stCannyInfo), 0, sizeof(s_stCannyInfo));
226 SAMPLE_COMM_IVE_CheckIveMpiInit();
227
228 s32Ret = SAMPLE_IVE_Canny_Init(&s_stCannyInfo, achSrcFileName, achDstFileName, u32Width, u32Height);
229 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, CANNY_FAIL, "Error(%#x),SAMPLE_IVE_Canny_Init failed!\n", s32Ret);
230 if (s_bStopSignal == HI_TRUE) {
231 SAMPLE_IVE_CannyStop();
232 return;
233 }
234
235 if (chComplete == '0') {
236 s32Ret = SAMPLE_IVE_Part_Canny(&s_stCannyInfo);
237 } else {
238 s32Ret = SAMPLE_IVE_Complete_Canny(&s_stCannyInfo);
239 }
240
241 if (s_bStopSignal == HI_TRUE) {
242 SAMPLE_IVE_CannyStop();
243 return;
244 }
245
246 if (s32Ret == HI_SUCCESS) {
247 SAMPLE_PRT("Process success!\n");
248 }
249
250 s_bStopSignal = HI_TRUE;
251 SAMPLE_IVE_Canny_Uninit(&s_stCannyInfo);
252 (HI_VOID)memset_s(&s_stCannyInfo, sizeof(s_stCannyInfo), 0, sizeof(s_stCannyInfo));
253
254 CANNY_FAIL:
255 s_bStopSignal = HI_TRUE;
256 SAMPLE_COMM_IVE_IveMpiExit();
257 }
258
SAMPLE_IVE_Canny_HandleSig(HI_VOID)259 HI_VOID SAMPLE_IVE_Canny_HandleSig(HI_VOID)
260 {
261 s_bStopSignal = HI_TRUE;
262 }
263