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 <sys/prctl.h>
28 #include <math.h>
29
30 #include "sample_comm_ive.h"
31
32 #define SAMPLE_IVE_OD_MAX_POINT 10
33 #define SAMPLE_IVE_OD_LINEAR_NUM 2
34 #define SAMPLE_IVE_OD_IDX_0 0
35 #define SAMPLE_IVE_OD_IDX_1 1
36 #define SAMPLE_IVE_OD_VAL_0 0
37 #define SAMPLE_IVE_OD_VAL_20 20
38 #define SAMPLE_IVE_OD_VAL_80 80
39 #define SAMPLE_IVE_OD_THR_NUM (IVE_CHAR_NUM / 2)
40 #define SAMPLE_IVE_OD_MASK 0xfffffffLL
41 #define SAMPLE_IVE_OD_MASK_BIT 28
42
43 typedef struct hiSAMPLE_IVE_OD_S {
44 IVE_SRC_IMAGE_S stSrc;
45 IVE_DST_IMAGE_S stInteg;
46 IVE_INTEG_CTRL_S stIntegCtrl;
47 HI_U32 u32W;
48 HI_U32 u32H;
49 } SAMPLE_IVE_OD_S;
50
51 static HI_BOOL s_bStopSignal = HI_FALSE;
52 static pthread_t s_hIveThread = 0;
53 static SAMPLE_IVE_OD_S s_stOd;
54 static SAMPLE_IVE_SWITCH_S s_stOdSwitch = { HI_FALSE, HI_TRUE };
55 static SAMPLE_VI_CONFIG_S s_stViConfig = { 0 };
56
SAMPLE_IVE_Od_Uninit(SAMPLE_IVE_OD_S * pstOd)57 static HI_VOID SAMPLE_IVE_Od_Uninit(SAMPLE_IVE_OD_S *pstOd)
58 {
59 IVE_MMZ_FREE(pstOd->stSrc.au64PhyAddr[0], pstOd->stSrc.au64VirAddr[0]);
60 IVE_MMZ_FREE(pstOd->stInteg.au64PhyAddr[0], pstOd->stInteg.au64VirAddr[0]);
61 }
62
SAMPLE_IVE_Od_Init(SAMPLE_IVE_OD_S * pstOd,HI_U32 u32Width,HI_U32 u32Height)63 static HI_S32 SAMPLE_IVE_Od_Init(SAMPLE_IVE_OD_S *pstOd, HI_U32 u32Width, HI_U32 u32Height)
64 {
65 HI_S32 s32Ret = HI_SUCCESS;
66 (HI_VOID)memset_s(pstOd, sizeof(SAMPLE_IVE_OD_S), 0, sizeof(SAMPLE_IVE_OD_S));
67 s32Ret = SAMPLE_COMM_IVE_CreateImage(&pstOd->stSrc, IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
68 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, OD_INIT_FAIL, "Error(%#x),Create src image failed!\n", s32Ret);
69 s32Ret = SAMPLE_COMM_IVE_CreateImage(&pstOd->stInteg, IVE_IMAGE_TYPE_U64C1, u32Width, u32Height);
70 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, OD_INIT_FAIL, "Error(%#x),Create integ image failed!\n", s32Ret);
71 pstOd->stIntegCtrl.enOutCtrl = IVE_INTEG_OUT_CTRL_COMBINE;
72 pstOd->u32W = u32Width / IVE_CHAR_CALW;
73 pstOd->u32H = u32Height / IVE_CHAR_CALH;
74
75 OD_INIT_FAIL:
76 if (s32Ret != HI_SUCCESS) {
77 SAMPLE_IVE_Od_Uninit(pstOd);
78 }
79 return s32Ret;
80 }
81
SAMPLE_IVE_Linear2DClassifer(POINT_S * pstChar,HI_S32 s32CharNum,POINT_S * pstLinearPoint,HI_S32 s32Linearnum)82 static HI_S32 SAMPLE_IVE_Linear2DClassifer(POINT_S *pstChar, HI_S32 s32CharNum, POINT_S *pstLinearPoint,
83 HI_S32 s32Linearnum)
84 {
85 HI_S32 s32ResultNum;
86 HI_S32 i, j;
87 HI_BOOL bTestFlag = HI_FALSE;
88 POINT_S *pstNextLinearPoint = NULL;
89
90 s32ResultNum = 0;
91 pstNextLinearPoint = &pstLinearPoint[1];
92 for (i = 0; i < s32CharNum; i++) {
93 bTestFlag = HI_TRUE;
94 for (j = 0; j < (s32Linearnum - 1); j++) {
95 if (((pstChar[i].s32Y - pstLinearPoint[j].s32Y) * (pstNextLinearPoint[j].s32X - pstLinearPoint[j].s32X) >
96 (pstChar[i].s32X - pstLinearPoint[j].s32X) * (pstNextLinearPoint[j].s32Y - pstLinearPoint[j].s32Y) &&
97 (pstNextLinearPoint[j].s32X != pstLinearPoint[j].s32X)) ||
98 ((pstChar[i].s32X > pstLinearPoint[j].s32X) &&
99 (pstNextLinearPoint[j].s32X == pstLinearPoint[j].s32X))) {
100 bTestFlag = HI_FALSE;
101 break;
102 }
103 }
104 if (HI_TRUE == bTestFlag) {
105 s32ResultNum++;
106 }
107 }
108 return s32ResultNum;
109 }
110
111
SAMPLE_IVE_OdProc(HI_VOID * pArgs)112 static HI_VOID *SAMPLE_IVE_OdProc(HI_VOID *pArgs)
113 {
114 HI_S32 s32Ret;
115 HI_U32 i, j;
116 SAMPLE_IVE_OD_S *pstOd = NULL;
117 VIDEO_FRAME_INFO_S stBaseFrmInfo;
118 VIDEO_FRAME_INFO_S stExtFrmInfo;
119 HI_S32 s32VpssGrp = 0;
120 HI_S32 as32VpssChn[] = {VPSS_CHN0, VPSS_CHN1};
121 HI_S32 s32MilliSec = SAMPLE_IVE_FRM_TIMEOUT;
122 IVE_DATA_S stSrc;
123 IVE_DATA_S stDst;
124 IVE_HANDLE IveHandle;
125 HI_BOOL bFinish = HI_FALSE;
126 HI_BOOL bBlock = HI_TRUE;
127 HI_BOOL bInstant = HI_TRUE;
128
129 POINT_S stChar[IVE_CHAR_NUM];
130 POINT_S astPoints[SAMPLE_IVE_OD_MAX_POINT] = {{0, 0}};
131 IVE_LINEAR_DATA_S stIveLinerData;
132 HI_U64 *pu64VirData = HI_NULL;
133 IVE_DMA_CTRL_S stDmaCtrl = { IVE_DMA_MODE_DIRECT_COPY, 0, 0, 0, 0 };
134
135 HI_U64 u64TopLeft, u64TopRight, u64BtmLeft, u64BtmRight;
136 HI_U64 *pu64TopRow = NULL;
137 HI_U64 *pu64BtmRow = NULL;
138 HI_U64 u64BlockSum, u64BlockSq;
139 HI_FLOAT fSqVar;
140 HI_S32 s32VoLayer = 0;
141 HI_S32 s32VoChn = 0;
142
143 pstOd = (SAMPLE_IVE_OD_S *)(pArgs);
144 pu64VirData = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U64, pstOd->stInteg.au64VirAddr[0]);
145
146 stIveLinerData.pstLinearPoint = &astPoints[0];
147 stIveLinerData.s32LinearNum = SAMPLE_IVE_OD_LINEAR_NUM; /* linear num: 2 */
148 stIveLinerData.s32ThreshNum = SAMPLE_IVE_OD_THR_NUM; /* threash num: IVE_CHAR_NUM / 2 */
149 stIveLinerData.pstLinearPoint[SAMPLE_IVE_OD_IDX_0].s32X = SAMPLE_IVE_OD_VAL_80; /* x value: 80 */
150 stIveLinerData.pstLinearPoint[SAMPLE_IVE_OD_IDX_0].s32Y = SAMPLE_IVE_OD_VAL_0; /* y value: 0 */
151 stIveLinerData.pstLinearPoint[SAMPLE_IVE_OD_IDX_1].s32X = SAMPLE_IVE_OD_VAL_80; /* x value: 80 */
152 stIveLinerData.pstLinearPoint[SAMPLE_IVE_OD_IDX_1].s32Y = SAMPLE_IVE_OD_VAL_20; /* y value: 20 */
153
154 while (s_bStopSignal == HI_FALSE) {
155 s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[1], &stExtFrmInfo, s32MilliSec);
156 if (s32Ret != HI_SUCCESS) {
157 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_GetChnFrame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", s32Ret, s32VpssGrp,
158 as32VpssChn[1]);
159 continue;
160 }
161
162 s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[0], &stBaseFrmInfo, s32MilliSec);
163 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXT_RELEASE,
164 "Error(%#x),HI_MPI_VPSS_GetChnFrame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", s32Ret, s32VpssGrp,
165 as32VpssChn[0]);
166
167 stSrc.u64VirAddr = stExtFrmInfo.stVFrame.u64VirAddr[0];
168 stSrc.u64PhyAddr = stExtFrmInfo.stVFrame.u64PhyAddr[0];
169 stSrc.u32Stride = stExtFrmInfo.stVFrame.u32Stride[0];
170 stSrc.u32Width = stExtFrmInfo.stVFrame.u32Width;
171 stSrc.u32Height = stExtFrmInfo.stVFrame.u32Height;
172
173 stDst.u64VirAddr = pstOd->stSrc.au64VirAddr[0];
174 stDst.u64PhyAddr = pstOd->stSrc.au64PhyAddr[0];
175 stDst.u32Stride = stExtFrmInfo.stVFrame.u32Stride[0];
176 stDst.u32Width = stExtFrmInfo.stVFrame.u32Width;
177 stDst.u32Height = stExtFrmInfo.stVFrame.u32Height;
178
179 bInstant = HI_FALSE;
180 s32Ret = HI_MPI_IVE_DMA(&IveHandle, &stSrc, &stDst, &stDmaCtrl, bInstant);
181 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "Error(%#x),HI_MPI_IVE_DMA failed!\n", s32Ret);
182
183 bInstant = HI_TRUE;
184 s32Ret = HI_MPI_IVE_Integ(&IveHandle, &pstOd->stSrc, &pstOd->stInteg, &pstOd->stIntegCtrl, bInstant);
185 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "Error(%#x),HI_MPI_IVE_Integ failed!\n", s32Ret);
186
187 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
188 while (s32Ret == HI_ERR_IVE_QUERY_TIMEOUT) {
189 usleep(IVE_QUERY_SLEEP_TIME); /* sleep 100 us */
190 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
191 }
192
193 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "Error(%#x),HI_MPI_IVE_Query failed!\n", s32Ret);
194
195 for (j = 0; j < IVE_CHAR_CALH; j++) {
196 pu64TopRow =
197 (j == 0) ? (pu64VirData) : (pu64VirData + (j * pstOd->u32H - 1) * pstOd->stInteg.au32Stride[0]);
198 pu64BtmRow = pu64VirData + ((j + 1) * pstOd->u32H - 1) * pstOd->stInteg.au32Stride[0];
199
200 for (i = 0; i < IVE_CHAR_CALW; i++) {
201 u64TopLeft = (j == 0) ? (0) : ((i == 0) ? (0) : (pu64TopRow[i * pstOd->u32W - 1]));
202 u64TopRight = (j == 0) ? (0) : (pu64TopRow[(i + 1) * pstOd->u32W - 1]);
203 u64BtmLeft = (i == 0) ? (0) : (pu64BtmRow[i * pstOd->u32W - 1]);
204 u64BtmRight = pu64BtmRow[(i + 1) * pstOd->u32W - 1];
205
206 u64BlockSum = (u64TopLeft & SAMPLE_IVE_OD_MASK) + (u64BtmRight & SAMPLE_IVE_OD_MASK) -
207 (u64BtmLeft & SAMPLE_IVE_OD_MASK) - (u64TopRight & SAMPLE_IVE_OD_MASK);
208
209 u64BlockSq = (u64TopLeft >> SAMPLE_IVE_OD_MASK_BIT) + (u64BtmRight >> SAMPLE_IVE_OD_MASK_BIT) -
210 (u64BtmLeft >> SAMPLE_IVE_OD_MASK_BIT) - (u64TopRight >> SAMPLE_IVE_OD_MASK_BIT); /* 28 bit */
211
212 // mean
213 stChar[j * IVE_CHAR_CALW + i].s32X = u64BlockSum / (pstOd->u32W * pstOd->u32H);
214 // sigma=sqrt(1/(w*h)*sum((x(i,j)-mean)^2)= sqrt(sum(x(i,j)^2)/(w*h)-mean^2)
215 fSqVar = u64BlockSq / (pstOd->u32W * pstOd->u32H) -
216 stChar[j * IVE_CHAR_CALW + i].s32X * stChar[j * IVE_CHAR_CALW + i].s32X;
217 stChar[j * IVE_CHAR_CALW + i].s32Y = (HI_U32)sqrt(fSqVar);
218 }
219 }
220
221 s32Ret = SAMPLE_IVE_Linear2DClassifer(&stChar[0], IVE_CHAR_NUM, stIveLinerData.pstLinearPoint,
222 stIveLinerData.s32LinearNum);
223 if (s32Ret > stIveLinerData.s32ThreshNum) {
224 SAMPLE_PRT("\033[0;31m Occlusion detected!\033[0;39m\n");
225 } else {
226 }
227 s32Ret = HI_MPI_VO_SendFrame(s32VoLayer, s32VoChn, &stBaseFrmInfo, s32MilliSec);
228 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "Error(%#x),SAMPLE_VO_SendFrame failed!\n", s32Ret);
229
230 BASE_RELEASE:
231 s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp, as32VpssChn[0], &stBaseFrmInfo);
232 if (s32Ret != HI_SUCCESS) {
233 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n", s32Ret, s32VpssGrp,
234 as32VpssChn[0]);
235 }
236
237 EXT_RELEASE:
238 s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp, as32VpssChn[1], &stExtFrmInfo);
239 if (s32Ret != HI_SUCCESS) {
240 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n", s32Ret, s32VpssGrp,
241 as32VpssChn[1]);
242 }
243 }
244 return HI_NULL;
245 }
246
SAMPLE_IVE_OdPause(HI_VOID)247 static HI_S32 SAMPLE_IVE_OdPause(HI_VOID)
248 {
249 printf("---------------press Enter key to exit!---------------\n");
250 if (s_bStopSignal == HI_TRUE) {
251 if (s_hIveThread != 0) {
252 pthread_join(s_hIveThread, HI_NULL);
253 s_hIveThread = 0;
254 }
255 SAMPLE_IVE_Od_Uninit(&(s_stOd));
256 (HI_VOID)memset_s(&s_stOd, sizeof(s_stOd), 0, sizeof(s_stOd));
257 SAMPLE_COMM_IVE_StopViVpssVencVo(&s_stViConfig, &s_stOdSwitch);
258 printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
259 return HI_FAILURE;
260 }
261 (HI_VOID)getchar();
262 if (s_bStopSignal == HI_TRUE) {
263 if (s_hIveThread != 0) {
264 pthread_join(s_hIveThread, HI_NULL);
265 s_hIveThread = 0;
266 }
267 SAMPLE_IVE_Od_Uninit(&(s_stOd));
268 (HI_VOID)memset_s(&s_stOd, sizeof(s_stOd), 0, sizeof(s_stOd));
269 SAMPLE_COMM_IVE_StopViVpssVencVo(&s_stViConfig, &s_stOdSwitch);
270
271 printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
272 return HI_FAILURE;
273 }
274 return HI_SUCCESS;
275 }
276
SAMPLE_IVE_Od(HI_VOID)277 HI_VOID SAMPLE_IVE_Od(HI_VOID)
278 {
279 SIZE_S stSize;
280 PIC_SIZE_E enSize = PIC_1080P;
281 HI_S32 s32Ret = HI_SUCCESS;
282
283 (HI_VOID)memset_s(&s_stOd, sizeof(s_stOd), 0, sizeof(s_stOd));
284 /* step 1: start vi vpss venc vo */
285 s32Ret = SAMPLE_COMM_IVE_StartViVpssVencVo(&s_stViConfig, &s_stOdSwitch, &enSize);
286 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_OD_0, "Error(%#x),SAMPLE_COMM_IVE_StartViVpssVencVo failed!\n",
287 s32Ret);
288
289 s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSize, &stSize);
290 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_OD_0, "Error(%#x),SAMPLE_COMM_SYS_GetPicSize failed!\n", s32Ret);
291 /* step 2: Init OD */
292 s32Ret = SAMPLE_IVE_Od_Init(&s_stOd, stSize.u32Width, stSize.u32Height);
293 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_OD_0, "SAMPLE_IVE_Od_Init failed, Error(%#x)!\n", s32Ret);
294 s_bStopSignal = HI_FALSE;
295 /* step 3: Create work thread */
296 s32Ret = prctl(PR_SET_NAME, "IVE_OdProc", 0, 0, 0);
297 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_OD_0, "thread set name failed!\n");
298 s32Ret = pthread_create(&s_hIveThread, 0, SAMPLE_IVE_OdProc, (HI_VOID *)&s_stOd);
299 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_OD_0, "thread create failed!\n");
300
301 s32Ret = SAMPLE_IVE_OdPause();
302 SAMPLE_CHECK_EXPR_RET_VOID(s32Ret != HI_SUCCESS, "pause failed!\n");
303
304 s_bStopSignal = HI_TRUE;
305 pthread_join(s_hIveThread, HI_NULL);
306 s_hIveThread = 0;
307 SAMPLE_IVE_Od_Uninit(&(s_stOd));
308 (HI_VOID)memset_s(&s_stOd, sizeof(s_stOd), 0, sizeof(s_stOd));
309
310 END_OD_0:
311 SAMPLE_COMM_IVE_StopViVpssVencVo(&s_stViConfig, &s_stOdSwitch);
312 return;
313 }
314
315 /* function : Od sample signal handle */
SAMPLE_IVE_Od_HandleSig(HI_VOID)316 HI_VOID SAMPLE_IVE_Od_HandleSig(HI_VOID)
317 {
318 s_bStopSignal = HI_TRUE;
319 }
320