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
28 #include "sample_comm_ive.h"
29
30 #define SAMPLE_IVE_GMM2_MAX(a, b) ((a) > (b) ? (a) : (b))
31 #define SAMPLE_IVE_GMM2_VAR_RATE 1
32 #define SAMPLE_IVE_GMM2_MODEL_NUM_3 3
33 #define SAMPLE_IVE_GMM2_MAX_VAR ((16 * 16) << 7)
34 #define SAMPLE_IVE_GMM2_MIN_VAR ((8 * 8) << 7)
35 #define SAMPLE_IVE_GMM2_GLB_SNS_FACTOR 8
36 #define SAMPLE_IVE_GMM2_FREQ_THR 12000
37 #define SAMPLE_IVE_GMM2_FREQ_INIT_VAL 20000
38 #define SAMPLE_IVE_GMM2_FREQ_ADD_FACTOR 0xEF
39 #define SAMPLE_IVE_GMM2_FREQ_REDU_FACTOR 0xFF00
40 #define SAMPLE_IVE_GMM2_LIFE_THR 5000
41 #define SAMPLE_IVE_GMM2_FACTOR_8 8
42 #define SAMPLE_IVE_GMM2_FACTOR_4 4
43 #define SAMPLE_IVE_GMM2_FACTOR_OFFSET 2
44 #define SAMPLE_IVE_GMM2_SRC_NUM 2
45 #define SAMPLE_IVE_GMM2_U8C1_MODLE_SIZE_UNIT 8
46 #define SAMPLE_IVE_GMM2_GEN_FG_MASK_MIN_VAL 0
47 #define SAMPLE_IVE_GMM2_GEN_FG_MASK_MAX_VAL 1
48 #define SAMPLE_IVE_GMM2_GEN_FG_MASK_LOW_THR 5
49 #define SAMPLE_IVE_GMM2_NUM_2 2
50 #define SAMPLE_IVE_GMM2_ABS_THR_10 10
51 #define SAMPLE_IVE_GMM2_FACTOR_16 16
52 #define SAMPLE_IVE_GMM2_FACTOR_20 20
53 #define SAMPLE_IVE_GMM2_FACTOR_200 200
54 #define SAMPLE_IVE_GMM2_TIMES_2 2
55 #define SAMPLE_IVE_GMM2_TIMES_3 3
56 #define SAMPLE_IVE_GMM2_TIMES_100 100
57 #define SAMPLE_IVE_GMM2_CCL_STEP 2
58 #define SAMPLE_IVE_GMM2_CCL_INIT_AREA_THR 4
59 #define SAMPLE_IVE_GMM2_16_TO_8_NUMERATOR 255
60 #define SAMPLE_IVE_GMM2_16_TO_8_DENOMINATOR (255 * 4)
61 #define SAMPLE_IVE_GMM2_MAX_AREA 60
62 #define SAMPLE_IVE_GMM2_MIN_GRAD_SUM 10
63 #define SAMPLE_IVE_GMM2_TOTAL_FRM 700
64 #define SAMPLE_IVE_GMM2_FRM_500 500
65 #define SAMPLE_IVE_GMM2_SMALL_FREQ_REDU_FACTOR 0xFC00
66 #define SAMPLE_IVE_GMM2_BIG_FREQ_REDU_FACTOR 0xFFA0
67
68 typedef struct hiSAMPLE_IVE_GMM2_S {
69 IVE_SRC_IMAGE_S astSrc[SAMPLE_IVE_GMM2_SRC_NUM];
70 IVE_DST_IMAGE_S stFg;
71 IVE_DST_IMAGE_S stBg;
72 IVE_SRC_IMAGE_S stFactor;
73 IVE_DST_IMAGE_S stMatchModelInfo;
74 IVE_SRC_IMAGE_S stFgMask;
75 IVE_SRC_IMAGE_S stLastImg;
76 IVE_DST_IMAGE_S stDiffImg;
77 IVE_DST_IMAGE_S stMagImg;
78 IVE_DST_IMAGE_S stCurNormMag;
79 IVE_DST_IMAGE_S stLastNormMag;
80 IVE_DST_MEM_INFO_S stModel;
81 IVE_DST_MEM_INFO_S stBlob;
82 IVE_GMM2_CTRL_S stGmm2Ctrl;
83 FILE *pFpSrc;
84 FILE *pFpFg;
85 FILE *pFpBg;
86 } SAMPLE_IVE_GMM2_S;
87
88 static SAMPLE_IVE_GMM2_S s_stGmm2;
89 static HI_BOOL s_bStopSignal = HI_FALSE;
90
SAMPLE_IVE_Gmm2_Uninit(SAMPLE_IVE_GMM2_S * pstGmm2)91 static HI_VOID SAMPLE_IVE_Gmm2_Uninit(SAMPLE_IVE_GMM2_S *pstGmm2)
92 {
93 HI_U16 i;
94 for (i = 0; i < SAMPLE_IVE_GMM2_SRC_NUM; i++) { /* max pstGmm2->astSrc index: 2 */
95 IVE_MMZ_FREE(pstGmm2->astSrc[i].au64PhyAddr[0], pstGmm2->astSrc[i].au64VirAddr[0]);
96 }
97 IVE_MMZ_FREE(pstGmm2->stFg.au64PhyAddr[0], pstGmm2->stFg.au64VirAddr[0]);
98 IVE_MMZ_FREE(pstGmm2->stBg.au64PhyAddr[0], pstGmm2->stBg.au64VirAddr[0]);
99 IVE_MMZ_FREE(pstGmm2->stFactor.au64PhyAddr[0], pstGmm2->stFactor.au64VirAddr[0]);
100 IVE_MMZ_FREE(pstGmm2->stMatchModelInfo.au64PhyAddr[0], pstGmm2->stMatchModelInfo.au64VirAddr[0]);
101 IVE_MMZ_FREE(pstGmm2->stFgMask.au64PhyAddr[0], pstGmm2->stFgMask.au64VirAddr[0]);
102 IVE_MMZ_FREE(pstGmm2->stDiffImg.au64PhyAddr[0], pstGmm2->stDiffImg.au64VirAddr[0]);
103 IVE_MMZ_FREE(pstGmm2->stMagImg.au64PhyAddr[0], pstGmm2->stMagImg.au64VirAddr[0]);
104 IVE_MMZ_FREE(pstGmm2->stCurNormMag.au64PhyAddr[0], pstGmm2->stCurNormMag.au64VirAddr[0]);
105 IVE_MMZ_FREE(pstGmm2->stLastNormMag.au64PhyAddr[0], pstGmm2->stLastNormMag.au64VirAddr[0]);
106 IVE_MMZ_FREE(pstGmm2->stModel.u64PhyAddr, pstGmm2->stModel.u64VirAddr);
107 IVE_MMZ_FREE(pstGmm2->stBlob.u64PhyAddr, pstGmm2->stBlob.u64VirAddr);
108
109 IVE_CLOSE_FILE(pstGmm2->pFpSrc);
110 IVE_CLOSE_FILE(pstGmm2->pFpFg);
111 IVE_CLOSE_FILE(pstGmm2->pFpBg);
112 }
113
SAMPLE_IVE_Gmm2_Init(SAMPLE_IVE_GMM2_S * pstGmm2,HI_U32 u32Width,HI_U32 u32Height,HI_CHAR * pchSrcFileName,HI_CHAR * pchFgFileName,HI_CHAR * pchBgFileName)114 static HI_S32 SAMPLE_IVE_Gmm2_Init(SAMPLE_IVE_GMM2_S *pstGmm2, HI_U32 u32Width, HI_U32 u32Height,
115 HI_CHAR *pchSrcFileName, HI_CHAR *pchFgFileName, HI_CHAR *pchBgFileName)
116 {
117 HI_S32 s32Ret = HI_SUCCESS;
118 HI_U32 u32Size;
119 HI_U16 i, j;
120 HI_U8 *pu8Tmp = NULL;
121 (HI_VOID)memset_s(pstGmm2, sizeof(SAMPLE_IVE_GMM2_S), 0, sizeof(SAMPLE_IVE_GMM2_S));
122
123 for (i = 0; i < SAMPLE_IVE_GMM2_SRC_NUM; i++) { /* max pstGmm2->astSrc index: 2 */
124 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->astSrc[i]), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
125 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create src[%d] image failed!\n",
126 s32Ret, i);
127 }
128
129 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stFg), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
130 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create fg image failed!\n", s32Ret);
131 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stBg), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
132 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create bg image failed!\n", s32Ret);
133 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stFactor), IVE_IMAGE_TYPE_U16C1, u32Width, u32Height);
134 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create factor image failed!\n", s32Ret);
135 pu8Tmp = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstGmm2->stFactor.au64VirAddr[0]);
136 for (i = 0; i < pstGmm2->stFactor.u32Height; i++) {
137 for (j = 0; j < pstGmm2->stFactor.u32Width; j++) {
138 pu8Tmp[SAMPLE_IVE_GMM2_FACTOR_OFFSET * j] = SAMPLE_IVE_GMM2_FACTOR_8; /* index: 2*j, value: 8 */
139 pu8Tmp[SAMPLE_IVE_GMM2_FACTOR_OFFSET * j + 1] = SAMPLE_IVE_GMM2_FACTOR_4; /* index: 2*j+1, value: 4 */
140 }
141 pu8Tmp += pstGmm2->stFactor.au32Stride[0] * sizeof(HI_U16);
142 }
143 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stMatchModelInfo), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
144 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create matchModelInfo image failed!\n",
145 s32Ret);
146 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stFgMask), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
147 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create fgMask image failed!\n", s32Ret);
148 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stDiffImg), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
149 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create diffImg image failed!\n", s32Ret);
150 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stMagImg), IVE_IMAGE_TYPE_U16C1, u32Width, u32Height);
151 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create magImg image failed!\n", s32Ret);
152 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stCurNormMag), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
153 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create curNormImg image failed!\n",
154 s32Ret);
155 s32Ret = SAMPLE_COMM_IVE_CreateImage(&(pstGmm2->stLastNormMag), IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
156 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create lastNormImg image failed!\n",
157 s32Ret);
158
159 pstGmm2->stGmm2Ctrl.u16VarRate = SAMPLE_IVE_GMM2_VAR_RATE;
160 pstGmm2->stGmm2Ctrl.u8ModelNum = SAMPLE_IVE_GMM2_MODEL_NUM_3; /* model num: 3 */
161 pstGmm2->stGmm2Ctrl.u9q7MaxVar = SAMPLE_IVE_GMM2_MAX_VAR; /* max var: (16 * 16) << 7 */
162 pstGmm2->stGmm2Ctrl.u9q7MinVar = SAMPLE_IVE_GMM2_MIN_VAR; /* min var: (8 * 8) << 7 */
163 pstGmm2->stGmm2Ctrl.u8GlbSnsFactor = SAMPLE_IVE_GMM2_GLB_SNS_FACTOR; /* sensor factor: 8 */
164 pstGmm2->stGmm2Ctrl.enSnsFactorMode = IVE_GMM2_SNS_FACTOR_MODE_PIX;
165 pstGmm2->stGmm2Ctrl.u16FreqThr = SAMPLE_IVE_GMM2_FREQ_THR; /* frequency threshold: 12000 */
166 pstGmm2->stGmm2Ctrl.u16FreqInitVal = SAMPLE_IVE_GMM2_FREQ_INIT_VAL; /* frequency init value: 20000 */
167 pstGmm2->stGmm2Ctrl.u16FreqAddFactor = SAMPLE_IVE_GMM2_FREQ_ADD_FACTOR; /* frequency add factor: 0xEF */
168 pstGmm2->stGmm2Ctrl.u16FreqReduFactor = SAMPLE_IVE_GMM2_FREQ_REDU_FACTOR; /* frequency redu factor: 0xFF00 */
169 pstGmm2->stGmm2Ctrl.u16LifeThr = SAMPLE_IVE_GMM2_LIFE_THR; /* life threshold: 5000 */
170 pstGmm2->stGmm2Ctrl.enLifeUpdateFactorMode = IVE_GMM2_LIFE_UPDATE_FACTOR_MODE_GLB;
171
172 u32Size = pstGmm2->stGmm2Ctrl.u8ModelNum * SAMPLE_IVE_GMM2_U8C1_MODLE_SIZE_UNIT *
173 pstGmm2->astSrc[0].u32Width * pstGmm2->astSrc[0].u32Height;
174 s32Ret = SAMPLE_COMM_IVE_CreateMemInfo(&pstGmm2->stModel, u32Size);
175 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create model mem info failed!\n", s32Ret);
176 (HI_VOID)memset_s(SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_VOID, pstGmm2->stModel.u64VirAddr),
177 pstGmm2->stModel.u32Size, 0, pstGmm2->stModel.u32Size);
178 u32Size = sizeof(IVE_CCBLOB_S);
179 s32Ret = SAMPLE_COMM_IVE_CreateMemInfo(&pstGmm2->stBlob, u32Size);
180 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_INIT_FAIL, "Error(%#x),Create blob mem info failed!\n", s32Ret);
181 s32Ret = HI_FAILURE;
182 pstGmm2->pFpSrc = fopen(pchSrcFileName, "rb");
183 SAMPLE_CHECK_EXPR_GOTO(pstGmm2->pFpSrc == NULL, GMM2_INIT_FAIL, "Error,Open file %s failed!\n", pchSrcFileName);
184 pstGmm2->pFpFg = fopen(pchFgFileName, "wb");
185 SAMPLE_CHECK_EXPR_GOTO(pstGmm2->pFpFg == NULL, GMM2_INIT_FAIL, "Error,Open file %s failed!\n", pchFgFileName);
186 pstGmm2->pFpBg = fopen(pchBgFileName, "wb");
187 SAMPLE_CHECK_EXPR_GOTO(pstGmm2->pFpBg == NULL, GMM2_INIT_FAIL, "Error,Open file %s failed!\n", pchBgFileName);
188 s32Ret = HI_SUCCESS;
189
190 GMM2_INIT_FAIL:
191 if (s32Ret != HI_SUCCESS) {
192 SAMPLE_IVE_Gmm2_Uninit(pstGmm2);
193 }
194 return s32Ret;
195 }
196
SAMPLE_IVE_GenFgMask(IVE_SRC_IMAGE_S * pstFg,IVE_DST_IMAGE_S * pstFgMask)197 static HI_S32 SAMPLE_IVE_GenFgMask(IVE_SRC_IMAGE_S *pstFg, IVE_DST_IMAGE_S *pstFgMask)
198 {
199 HI_S32 s32Ret;
200 IVE_HANDLE IveHandle;
201 IVE_THRESH_CTRL_S stCtrl;
202
203 stCtrl.enMode = IVE_THRESH_MODE_BINARY;
204 stCtrl.u8MinVal = SAMPLE_IVE_GMM2_GEN_FG_MASK_MIN_VAL;
205 stCtrl.u8MaxVal = SAMPLE_IVE_GMM2_GEN_FG_MASK_MAX_VAL;
206 stCtrl.u8LowThr = SAMPLE_IVE_GMM2_GEN_FG_MASK_LOW_THR; /* low threshold: 5 */
207 s32Ret = HI_MPI_IVE_Thresh(&IveHandle, pstFg, pstFgMask, &stCtrl, HI_FALSE);
208 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Thresh failed!\n", s32Ret);
209
210 return s32Ret;
211 }
212
213 /* Reduce the factor gradually to the default value */
SAMPLE_IVE_ReduFactor(IVE_IMAGE_S * pstFactor)214 static HI_VOID SAMPLE_IVE_ReduFactor(IVE_IMAGE_S *pstFactor)
215 {
216 HI_U16 i, j;
217 HI_U8 *pu8Tmp = NULL;
218
219 pu8Tmp = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstFactor->au64VirAddr[0]);
220 for (i = 0; i < pstFactor->u32Height; i++) {
221 for (j = 0; j < pstFactor->u32Width; j++) {
222 pu8Tmp[j << 1] = SAMPLE_IVE_GMM2_MAX(SAMPLE_IVE_GMM2_FACTOR_8, pu8Tmp[i << 1] - 1);
223 pu8Tmp[(i << 1) + 1] = SAMPLE_IVE_GMM2_MAX(SAMPLE_IVE_GMM2_FACTOR_8,
224 pu8Tmp[(i << 1) + 1] - SAMPLE_IVE_GMM2_NUM_2);
225 }
226 pu8Tmp += pstFactor->au32Stride[0] * sizeof(HI_U16);
227 }
228 }
229
230 /* Change factor by difference frame */
SAMPLE_IVE_ChgFactorByDiffFrm(IVE_SRC_IMAGE_S * pstSrc,IVE_SRC_IMAGE_S * pstLastImg,IVE_DST_IMAGE_S * pstDiffImg,IVE_DST_IMAGE_S * pstFactor)231 static HI_BOOL SAMPLE_IVE_ChgFactorByDiffFrm(IVE_SRC_IMAGE_S *pstSrc, IVE_SRC_IMAGE_S *pstLastImg,
232 IVE_DST_IMAGE_S *pstDiffImg, IVE_DST_IMAGE_S *pstFactor)
233 {
234 HI_S32 s32Ret;
235 IVE_HANDLE IveHandle;
236 HI_BOOL bFinish = HI_FALSE;
237 HI_BOOL bBlock = HI_TRUE;
238 HI_U16 i, j;
239 HI_S32 s32AbsTh = SAMPLE_IVE_GMM2_ABS_THR_10;
240 HI_U32 u32PointSum = 0;
241 IVE_SUB_CTRL_S stSubCtrl;
242 HI_U8 *pu8Tmp = NULL;
243 HI_U8 *pu8Factor = NULL;
244
245 stSubCtrl.enMode = IVE_SUB_MODE_ABS;
246 s32Ret = HI_MPI_IVE_Sub(&IveHandle, pstSrc, pstLastImg, pstDiffImg, &stSubCtrl, HI_TRUE);
247 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, HI_FALSE, "Error(%#x),HI_MPI_IVE_Sub failed!\n", s32Ret);
248
249 // Wait task finish
250 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
251 while (s32Ret == HI_ERR_IVE_QUERY_TIMEOUT) {
252 usleep(IVE_QUERY_SLEEP_TIME); /* sleep 100 us */
253 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
254 }
255
256 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, HI_FALSE, "Error(%#x),HI_MPI_IVE_Query failed!\n", s32Ret);
257
258 pu8Tmp = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstDiffImg->au64VirAddr[0]);
259 for (i = 0; i < pstSrc->u32Height; i++) {
260 for (j = 0; j < pstSrc->u32Width; j++) {
261 u32PointSum += pu8Tmp[j] > s32AbsTh;
262 }
263 pu8Tmp += pstDiffImg->au32Stride[0];
264 }
265
266 if ((u32PointSum * SAMPLE_IVE_GMM2_TIMES_3) > (pstSrc->u32Width * pstSrc->u32Height * SAMPLE_IVE_GMM2_TIMES_2)) {
267 pu8Tmp = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstDiffImg->au64VirAddr[0]);
268 pu8Factor = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstFactor->au64VirAddr[0]);
269 for (i = 0; i < pstSrc->u32Height; i++) {
270 for (j = 0; j < pstSrc->u32Width; j++) {
271 if (pu8Tmp[j] > s32AbsTh) {
272 pu8Factor[j << 1] = SAMPLE_IVE_GMM2_FACTOR_20; /* set 20 */
273 pu8Factor[(j << 1) + 1] = SAMPLE_IVE_GMM2_FACTOR_200; /* set 200 */
274 }
275 }
276 pu8Tmp += pstDiffImg->au32Stride[0];
277 pu8Factor += pstFactor->au32Stride[0] * sizeof(HI_U16);
278 }
279
280 return HI_TRUE;
281 }
282
283 return HI_FALSE;
284 }
285
286 /* Change factor by gradient */
SAMPLE_IVE_ChgFactorByGrad(IVE_SRC_IMAGE_S * pstFgMask,IVE_SRC_IMAGE_S * pstSrc,IVE_SRC_IMAGE_S * pstLastImg,IVE_SRC_IMAGE_S * pstLastNormMag,IVE_DST_IMAGE_S * pstMagImg,IVE_DST_IMAGE_S * pstCurNormMag,IVE_DST_MEM_INFO_S * pstBlob,IVE_DST_IMAGE_S * pstDiffImg,IVE_DST_IMAGE_S * pstFactor)287 static HI_S32 SAMPLE_IVE_ChgFactorByGrad(IVE_SRC_IMAGE_S *pstFgMask, IVE_SRC_IMAGE_S *pstSrc,
288 IVE_SRC_IMAGE_S *pstLastImg, IVE_SRC_IMAGE_S *pstLastNormMag, IVE_DST_IMAGE_S *pstMagImg,
289 IVE_DST_IMAGE_S *pstCurNormMag, IVE_DST_MEM_INFO_S *pstBlob, IVE_DST_IMAGE_S *pstDiffImg,
290 IVE_DST_IMAGE_S *pstFactor)
291 {
292 HI_S32 s32Ret;
293 IVE_HANDLE IveHandle;
294 HI_BOOL bFinish = HI_FALSE;
295 HI_BOOL bBlock = HI_TRUE;
296 HI_U16 i, j, k;
297 HI_U16 u16Top;
298 HI_U16 u16Left;
299 HI_U16 u16Right;
300 HI_U16 u16Bottom;
301 HI_U8 *pu8FgCur = NULL;
302 HI_U8 *pu8GradDiff = NULL;
303 HI_U8 *pu8Factor = NULL;
304 HI_S32 s32FgSum = 0;
305 HI_S32 s32GradSum = 0;
306 /* mag filter mask */
307 HI_S8 au8Mask[IVE_MASK_NUM_25] = {
308 0, 0, 0, 0, 0,
309 0, -1, 0, 1, 0,
310 0, -2, 0, 2, 0,
311 0, -1, 0, 1, 0,
312 0, 0, 0, 0, 0};
313 IVE_CCL_CTRL_S stCclCtrl;
314 IVE_CCBLOB_S *pstCclBlob = NULL;
315 IVE_MAG_AND_ANG_CTRL_S stMagAndAngCtrl;
316 IVE_16BIT_TO_8BIT_CTRL_S st16To8Ctrl;
317 IVE_SUB_CTRL_S stSubCtrl;
318
319 stCclCtrl.enMode = IVE_CCL_MODE_8C;
320 stCclCtrl.u16Step = SAMPLE_IVE_GMM2_CCL_STEP; /* set 2 */
321 stCclCtrl.u16InitAreaThr = SAMPLE_IVE_GMM2_CCL_INIT_AREA_THR; /* set 4 */
322 s32Ret = HI_MPI_IVE_CCL(&IveHandle, pstFgMask, pstBlob, &stCclCtrl, HI_TRUE);
323 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_CCL failed!\n", s32Ret);
324
325 // Wait task finish
326 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
327 while (s32Ret == HI_ERR_IVE_QUERY_TIMEOUT) {
328 usleep(IVE_QUERY_SLEEP_TIME); /* sleep 100 us */
329 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
330 }
331 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Query failed!\n", s32Ret);
332
333 pstCclBlob = SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(IVE_CCBLOB_S, pstBlob->u64VirAddr);
334 if (pstCclBlob->u8RegionNum > 0) {
335 // Calc the gradient difference of the current image and the last image
336 (HI_VOID)memcpy_s(stMagAndAngCtrl.as8Mask, sizeof(au8Mask), au8Mask, sizeof(au8Mask));
337 stMagAndAngCtrl.u16Thr = 0;
338 stMagAndAngCtrl.enOutCtrl = IVE_MAG_AND_ANG_OUT_CTRL_MAG;
339 s32Ret = HI_MPI_IVE_MagAndAng(&IveHandle, pstSrc, pstMagImg, HI_NULL, &stMagAndAngCtrl, HI_FALSE);
340 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_MagAndAng failed!\n", s32Ret);
341
342 st16To8Ctrl.s8Bias = 0;
343 st16To8Ctrl.enMode = IVE_16BIT_TO_8BIT_MODE_U16_TO_U8;
344 st16To8Ctrl.u8Numerator = SAMPLE_IVE_GMM2_16_TO_8_NUMERATOR; /* numerator: 255 */
345 st16To8Ctrl.u16Denominator = SAMPLE_IVE_GMM2_16_TO_8_DENOMINATOR; /* Denominator: 255*4 */
346 s32Ret = HI_MPI_IVE_16BitTo8Bit(&IveHandle, pstMagImg, pstCurNormMag, &st16To8Ctrl, HI_FALSE);
347 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_16BitTo8Bit failed!\n", s32Ret);
348 s32Ret = HI_MPI_IVE_MagAndAng(&IveHandle, pstLastImg, pstMagImg, HI_NULL, &stMagAndAngCtrl, HI_FALSE);
349 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_MagAndAng failed!\n", s32Ret);
350 s32Ret = HI_MPI_IVE_16BitTo8Bit(&IveHandle, pstMagImg, pstLastNormMag, &st16To8Ctrl, HI_FALSE);
351 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_16BitTo8Bit failed!\n", s32Ret);
352 stSubCtrl.enMode = IVE_SUB_MODE_ABS;
353 s32Ret = HI_MPI_IVE_Sub(&IveHandle, pstCurNormMag, pstLastNormMag, pstDiffImg, &stSubCtrl, HI_TRUE);
354 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Sub failed!\n", s32Ret);
355 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
356 while (s32Ret == HI_ERR_IVE_QUERY_TIMEOUT) {
357 usleep(IVE_QUERY_SLEEP_TIME); /* sleep 100 us */
358 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
359 }
360
361 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Query failed!\n", s32Ret);
362 }
363
364 // for each blob, analyze the gradient change
365 for (k = 0; k < IVE_MAX_REGION_NUM; k++) {
366 if (pstCclBlob->astRegion[k].u32Area == 0) {
367 continue;
368 }
369
370 u16Top = pstCclBlob->astRegion[k].u16Top;
371 u16Left = pstCclBlob->astRegion[k].u16Left;
372 u16Right = pstCclBlob->astRegion[k].u16Right;
373 u16Bottom = pstCclBlob->astRegion[k].u16Bottom;
374 if ((u16Right - u16Left) * (u16Bottom - u16Top) < SAMPLE_IVE_GMM2_MAX_AREA) { /* max area: 60 */
375 continue;
376 }
377
378 s32FgSum = 0;
379 s32GradSum = 0;
380 pu8FgCur =
381 (SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstFgMask->au64VirAddr[0])) + u16Top * pstFgMask->au32Stride[0];
382 pu8GradDiff = (SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstDiffImg->au64VirAddr[0])) +
383 u16Top * pstDiffImg->au32Stride[0];
384 for (i = u16Top; i < u16Bottom; i++) {
385 for (j = u16Left; j < u16Right; j++) {
386 if (pu8FgCur[j]) {
387 s32FgSum++;
388 if (pu8GradDiff[j]) {
389 s32GradSum++;
390 }
391 }
392 }
393
394 pu8FgCur += pstFgMask->au32Stride[0];
395 pu8GradDiff += pstDiffImg->au32Stride[0];
396 }
397 /* s32GradSum: 100, s32GradSum * 100: s32FgSum */
398 if ((s32GradSum < SAMPLE_IVE_GMM2_MIN_GRAD_SUM) || (s32GradSum * SAMPLE_IVE_GMM2_TIMES_100 < s32FgSum)) {
399 pu8Factor = (SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstFactor->au64VirAddr[0])) +
400 SAMPLE_IVE_GMM2_FACTOR_OFFSET * u16Top * pstFactor->au32Stride[0];
401 pu8FgCur = (SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(HI_U8, pstFgMask->au64VirAddr[0])) +
402 u16Top * pstFgMask->au32Stride[0];
403 for (i = u16Top; i < u16Bottom; i++) {
404 for (j = u16Left; j < u16Right; j++) {
405 if (pu8FgCur[j]) {
406 pu8Factor[j << 1] = SAMPLE_IVE_GMM2_FACTOR_16; /* fator[j<<1] value: 16 */
407 pu8Factor[(j << 1) + 1] = SAMPLE_IVE_GMM2_FACTOR_200; /* fator[(j << 1) + 1] value: 200 */
408 }
409 }
410 pu8FgCur += pstFgMask->au32Stride[0];
411 pu8Factor += pstFactor->au32Stride[0] * sizeof(HI_U16);
412 }
413 }
414 }
415
416 return HI_SUCCESS;
417 }
418
SAMPLE_IVE_AdjustmentFactor(IVE_SRC_IMAGE_S * pstFactor,IVE_SRC_IMAGE_S * pstFgMask,IVE_SRC_IMAGE_S * pstSrc,IVE_SRC_IMAGE_S * pstLastImg,IVE_DST_IMAGE_S * pstDiffImg,IVE_DST_IMAGE_S * pstMagImg,IVE_DST_IMAGE_S * pstCurNormMag,IVE_DST_IMAGE_S * pstLastNormMag,IVE_DST_MEM_INFO_S * pstBlob)419 static HI_VOID SAMPLE_IVE_AdjustmentFactor(IVE_SRC_IMAGE_S *pstFactor, IVE_SRC_IMAGE_S *pstFgMask,
420 IVE_SRC_IMAGE_S *pstSrc, IVE_SRC_IMAGE_S *pstLastImg, IVE_DST_IMAGE_S *pstDiffImg, IVE_DST_IMAGE_S *pstMagImg,
421 IVE_DST_IMAGE_S *pstCurNormMag, IVE_DST_IMAGE_S *pstLastNormMag, IVE_DST_MEM_INFO_S *pstBlob)
422 {
423 HI_BOOL bChg = HI_FALSE;
424 // First, reduce the factor gradually to the default value------------------------------
425 SAMPLE_IVE_ReduFactor(pstFactor);
426
427 // Second, analyze the frame difference-------------------------------------------------
428 // When the number of changed pixels is more than the threshold, there maybe a light switch.
429 // And then, we should set a big factor to adapt to it quickly.
430 bChg = SAMPLE_IVE_ChgFactorByDiffFrm(pstSrc, pstLastImg, pstDiffImg, pstFactor);
431 if (HI_TRUE == bChg) {
432 return;
433 }
434
435 // Third, analyze the gradient for foreground blobs------------------------------------
436 // When gradient change of a foreground blob is very small, it maybe a local illumination change,
437 // a ghost, or a static object.
438 // Here we try to reduce the influence by a local illumination change or a ghost only.
439 (HI_VOID)SAMPLE_IVE_ChgFactorByGrad(pstFgMask, pstSrc, pstLastImg, pstLastNormMag, pstMagImg, pstCurNormMag,
440 pstBlob, pstDiffImg, pstFactor);
441 }
442
SAMPLE_IVE_Gmm2Proc(SAMPLE_IVE_GMM2_S * pstGmm2)443 static HI_S32 SAMPLE_IVE_Gmm2Proc(SAMPLE_IVE_GMM2_S *pstGmm2)
444 {
445 HI_S32 s32Ret = HI_FAILURE;
446 IVE_HANDLE IveHandle;
447 HI_BOOL bFinish = HI_FALSE;
448 HI_BOOL bBlock = HI_TRUE;
449 HI_BOOL bInstant = HI_TRUE;
450 HI_U32 u32FrmNum;
451 HI_S32 s32CurIdx = 0;
452 HI_U32 u32TotalFrm = SAMPLE_IVE_GMM2_TOTAL_FRM;
453
454 for (u32FrmNum = 1; u32FrmNum < u32TotalFrm && s_bStopSignal == HI_FALSE; u32FrmNum++) {
455 SAMPLE_PRT("Proc Frame %d/%d\n", u32FrmNum, u32TotalFrm);
456 s32Ret = SAMPLE_COMM_IVE_ReadFile(&(pstGmm2->astSrc[s32CurIdx]), pstGmm2->pFpSrc);
457 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),Read src file failed!\n", s32Ret);
458
459 // To building a stable background model quickly at the begin, some parameters are set specially.
460 if (pstGmm2->stGmm2Ctrl.u8ModelNum == 1) {
461 // If the parameter u8ModelNum is set to 1, the parameter u16FreqReduFactor
462 // is usually set to a small value at the first N frames. Here, N = 500.
463 pstGmm2->stGmm2Ctrl.u16FreqReduFactor = (u32FrmNum >= SAMPLE_IVE_GMM2_FRM_500) ?
464 SAMPLE_IVE_GMM2_BIG_FREQ_REDU_FACTOR : SAMPLE_IVE_GMM2_SMALL_FREQ_REDU_FACTOR;
465 } else {
466 // If the parameter u8ModelNum is more than 1, the global life mode should be used at the first N frames,
467 // and the parameter u16GlbLifeUpdateFactor is usually set to a big value. Here, N = 500.
468 if (u32FrmNum >= 500) {
469 pstGmm2->stGmm2Ctrl.enLifeUpdateFactorMode = IVE_GMM2_LIFE_UPDATE_FACTOR_MODE_PIX;
470 } else {
471 pstGmm2->stGmm2Ctrl.u16GlbLifeUpdateFactor = 0xFFFF / u32FrmNum;
472 }
473 }
474
475 // GMM2
476 s32Ret = HI_MPI_IVE_GMM2(&IveHandle, &pstGmm2->astSrc[s32CurIdx], &pstGmm2->stFactor, &pstGmm2->stFg,
477 &pstGmm2->stBg, &pstGmm2->stMatchModelInfo, &pstGmm2->stModel, &pstGmm2->stGmm2Ctrl, bInstant);
478 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_GMM2 failed!\n", s32Ret);
479
480 // factor adjustment
481 if (u32FrmNum > 1) {
482 s32Ret = SAMPLE_IVE_GenFgMask(&(pstGmm2->stFg), &(pstGmm2->stFgMask));
483 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),SAMPLE_IVE_GenFgMask failed!\n", s32Ret);
484
485 SAMPLE_IVE_AdjustmentFactor(&(pstGmm2->stFactor), &(pstGmm2->stFgMask), &(pstGmm2->astSrc[s32CurIdx]),
486 &(pstGmm2->astSrc[1 - s32CurIdx]), &(pstGmm2->stDiffImg), &(pstGmm2->stMagImg),
487 &(pstGmm2->stCurNormMag), &(pstGmm2->stLastNormMag), &(pstGmm2->stBlob));
488 } else {
489 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
490 while (s32Ret == HI_ERR_IVE_QUERY_TIMEOUT) {
491 usleep(IVE_QUERY_SLEEP_TIME); /* sleep 100 us */
492 s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
493 }
494 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),HI_MPI_IVE_Query failed!\n", s32Ret);
495 }
496
497 s32Ret = SAMPLE_COMM_IVE_WriteFile(&(pstGmm2->stFg), pstGmm2->pFpFg);
498 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),Write fg file failed!\n", s32Ret);
499 s32Ret = SAMPLE_COMM_IVE_WriteFile(&(pstGmm2->stBg), pstGmm2->pFpBg);
500 SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Error(%#x),Write bg file failed!\n", s32Ret);
501 // change cur image to last image
502 s32CurIdx = 1 - s32CurIdx;
503 }
504
505 return s32Ret;
506 }
507
SAMPLE_IVE_GMM2Stop(HI_VOID)508 static HI_VOID SAMPLE_IVE_GMM2Stop(HI_VOID)
509 {
510 SAMPLE_IVE_Gmm2_Uninit(&s_stGmm2);
511 (HI_VOID)memset_s(&s_stGmm2, sizeof(s_stGmm2), 0, sizeof(s_stGmm2));
512 SAMPLE_COMM_IVE_IveMpiExit();
513 printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
514 }
515
SAMPLE_IVE_Gmm2(HI_VOID)516 HI_VOID SAMPLE_IVE_Gmm2(HI_VOID)
517 {
518 HI_S32 s32Ret;
519 HI_U32 u32Width = IVE_CIF_WIDTH;
520 HI_U32 u32Height = IVE_CIF_HEIGHT;
521 HI_CHAR *pchSrcFileName = "./data/input/gmm2/gmm2_352x288_sp400_frm1000.yuv";
522 HI_CHAR achSrcFileName[PATH_MAX] = {0};
523 HI_CHAR achFgFileName[PATH_MAX] = {0};
524 HI_CHAR achBgFileName[PATH_MAX] = {0};
525
526 s_bStopSignal = HI_FALSE;
527 SAMPLE_CHECK_EXPR_RET_VOID(
528 (strlen(pchSrcFileName) > PATH_MAX) || (realpath(pchSrcFileName, achSrcFileName) == NULL), "invalid path!\n");
529 SAMPLE_CHECK_EXPR_RET_VOID(realpath("./data/output/gmm2", achFgFileName) == NULL, "invalid path");
530 s32Ret = strcat_s(achFgFileName, PATH_MAX, "/fg_352x288_sp400.yuv");
531 SAMPLE_CHECK_EXPR_RET_VOID(s32Ret < 0, "invali param");
532 SAMPLE_CHECK_EXPR_RET_VOID(strlen(achFgFileName) > PATH_MAX, "fg file path is invalid!\n");
533 SAMPLE_CHECK_EXPR_RET_VOID(realpath("./data/output/gmm2", achBgFileName) == NULL, "invalid path");
534 s32Ret = strcat_s(achBgFileName, PATH_MAX, "/bg_352x288_sp400.yuv");
535 SAMPLE_CHECK_EXPR_RET_VOID(s32Ret < 0, "invali param");
536 SAMPLE_CHECK_EXPR_RET_VOID(strlen(achBgFileName) > PATH_MAX, "bg file path is invalid!\n");
537 (HI_VOID)memset_s(&s_stGmm2, sizeof(s_stGmm2), 0, sizeof(s_stGmm2));
538 SAMPLE_COMM_IVE_CheckIveMpiInit();
539 s32Ret = SAMPLE_IVE_Gmm2_Init(&s_stGmm2, u32Width, u32Height, achSrcFileName, achFgFileName, achBgFileName);
540 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, GMM2_FAIL, "Error(%#x),SAMPLE_IVE_Gmm2_Init failed!\n", s32Ret);
541 if (s_bStopSignal == HI_TRUE) {
542 SAMPLE_IVE_GMM2Stop();
543 return;
544 }
545
546 s32Ret = SAMPLE_IVE_Gmm2Proc(&s_stGmm2);
547 if (s32Ret == HI_SUCCESS) {
548 SAMPLE_PRT("Process success!\n");
549 }
550
551 if (s_bStopSignal == HI_TRUE) {
552 SAMPLE_IVE_GMM2Stop();
553 return;
554 }
555 s_bStopSignal = HI_TRUE;
556
557 SAMPLE_IVE_Gmm2_Uninit(&s_stGmm2);
558 (HI_VOID)memset_s(&s_stGmm2, sizeof(s_stGmm2), 0, sizeof(s_stGmm2));
559
560 GMM2_FAIL:
561 s_bStopSignal = HI_TRUE;
562 SAMPLE_COMM_IVE_IveMpiExit();
563 }
564
SAMPLE_IVE_Gmm2_HandleSig(HI_VOID)565 HI_VOID SAMPLE_IVE_Gmm2_HandleSig(HI_VOID)
566 {
567 s_bStopSignal = HI_TRUE;
568 }
569