• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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