• 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 
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