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
29 #include "sample_comm_ive.h"
30 #include "ivs_md.h"
31
32 #define SAMPLE_IVE_MD_IMAGE_NUM 2
33 #define SAMPLE_IVE_MD_X_WEIGHT 32768
34 #define SAMPLE_IVE_MD_Y_WEIGHT 32768
35 #define SAMPLE_IVE_MD_SAD_THR (100 * (1 << 1))
36 #define SAMPLE_IVE_MD_CAL_WIN_SIZE(mod) (1 << (2 + (mod)))
37 #define SAMPLE_IVE_MD_AREA_THR_STEP 8
38 #define SAMPLE_IVE_MD_COLOR 0x0000FF00
39
40 typedef struct hiSAMPLE_IVE_MD_S {
41 IVE_SRC_IMAGE_S astImg[SAMPLE_IVE_MD_IMAGE_NUM];
42 IVE_DST_MEM_INFO_S stBlob;
43 MD_ATTR_S stMdAttr;
44 SAMPLE_RECT_ARRAY_S stRegion;
45 } SAMPLE_IVE_MD_S;
46
47 static HI_BOOL s_bStopSignal = HI_FALSE;
48 static pthread_t s_hMdThread = 0;
49 static SAMPLE_IVE_MD_S s_stMd;
50 static SAMPLE_IVE_SWITCH_S s_stMdSwitch = { HI_FALSE, HI_TRUE };
51 static SAMPLE_VI_CONFIG_S s_stViConfig = { 0 };
52
SAMPLE_IVE_Md_Uninit(SAMPLE_IVE_MD_S * pstMd)53 static HI_VOID SAMPLE_IVE_Md_Uninit(SAMPLE_IVE_MD_S *pstMd)
54 {
55 HI_S32 i;
56 HI_S32 s32Ret = HI_SUCCESS;
57
58 for (i = 0; i < SAMPLE_IVE_MD_IMAGE_NUM; i++) {
59 IVE_MMZ_FREE(pstMd->astImg[i].au64PhyAddr[0], pstMd->astImg[i].au64VirAddr[0]);
60 }
61
62 IVE_MMZ_FREE(pstMd->stBlob.u64PhyAddr, pstMd->stBlob.u64VirAddr);
63
64 s32Ret = HI_IVS_MD_Exit();
65 if (s32Ret != HI_SUCCESS) {
66 SAMPLE_PRT("HI_IVS_MD_Exit fail,Error(%#x)\n", s32Ret);
67 return;
68 }
69 }
70
SAMPLE_IVE_Md_Init(SAMPLE_IVE_MD_S * pstMd,HI_U32 u32Width,HI_U32 u32Height)71 static HI_S32 SAMPLE_IVE_Md_Init(SAMPLE_IVE_MD_S *pstMd, HI_U32 u32Width, HI_U32 u32Height)
72 {
73 HI_S32 s32Ret = HI_SUCCESS;
74 HI_S32 i;
75 HI_U32 u32Size;
76 HI_U8 u8WndSz;
77 HI_U8 u8SadMode = pstMd->stMdAttr.enSadMode;
78
79 for (i = 0; i < SAMPLE_IVE_MD_IMAGE_NUM; i++) {
80 s32Ret = SAMPLE_COMM_IVE_CreateImage(&pstMd->astImg[i], IVE_IMAGE_TYPE_U8C1, u32Width, u32Height);
81 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, MD_INIT_FAIL, "Error(%#x),Create img[%d] image failed!\n", s32Ret,
82 i);
83 }
84 u32Size = sizeof(IVE_CCBLOB_S);
85 s32Ret = SAMPLE_COMM_IVE_CreateMemInfo(&pstMd->stBlob, u32Size);
86 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, MD_INIT_FAIL, "Error(%#x),Create blob mem info failed!\n", s32Ret);
87
88 // Set attr info
89 pstMd->stMdAttr.enAlgMode = MD_ALG_MODE_BG;
90 pstMd->stMdAttr.enSadMode = IVE_SAD_MODE_MB_4X4;
91 pstMd->stMdAttr.enSadOutCtrl = IVE_SAD_OUT_CTRL_THRESH;
92 pstMd->stMdAttr.u16SadThr = SAMPLE_IVE_MD_SAD_THR; // 100 * (1 << 2);
93 pstMd->stMdAttr.u32Width = u32Width;
94 pstMd->stMdAttr.u32Height = u32Height;
95 pstMd->stMdAttr.stAddCtrl.u0q16X = SAMPLE_IVE_MD_X_WEIGHT; // X: 32768
96 pstMd->stMdAttr.stAddCtrl.u0q16Y = SAMPLE_IVE_MD_Y_WEIGHT; // Y: 32768
97 pstMd->stMdAttr.stCclCtrl.enMode = IVE_CCL_MODE_4C;
98 u8WndSz = SAMPLE_IVE_MD_CAL_WIN_SIZE(u8SadMode); // (2 + u8SadMode) bit
99 pstMd->stMdAttr.stCclCtrl.u16InitAreaThr = u8WndSz * u8WndSz;
100 pstMd->stMdAttr.stCclCtrl.u16Step = u8WndSz;
101
102 s32Ret = HI_IVS_MD_Init();
103 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, MD_INIT_FAIL, "Error(%#x),HI_IVS_MD_Init failed!\n", s32Ret);
104
105 MD_INIT_FAIL:
106
107 if (s32Ret != HI_SUCCESS) {
108 SAMPLE_IVE_Md_Uninit(pstMd);
109 }
110 return s32Ret;
111 }
SAMPLE_IVE_MdProc(HI_VOID * pArgs)112 static HI_VOID *SAMPLE_IVE_MdProc(HI_VOID *pArgs)
113 {
114 HI_S32 s32Ret;
115 SAMPLE_IVE_MD_S *pstMd = NULL;
116 MD_ATTR_S *pstMdAttr = 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 MD_CHN MdChn = 0;
123 VO_LAYER voLayer = 0;
124 VO_CHN voChn = 0;
125 HI_BOOL bInstant = HI_TRUE;
126 HI_S32 s32CurIdx = 0;
127 HI_BOOL bFirstFrm = HI_TRUE;
128 pstMd = (SAMPLE_IVE_MD_S *)(pArgs);
129 pstMdAttr = &(pstMd->stMdAttr);
130 // Create chn
131 s32Ret = HI_IVS_MD_CreateChn(MdChn, &(pstMd->stMdAttr));
132 if (s32Ret != HI_SUCCESS) {
133 SAMPLE_PRT("HI_IVS_MD_CreateChn fail,Error(%#x)\n", s32Ret);
134 return NULL;
135 }
136
137 while (HI_FALSE == s_bStopSignal) {
138 s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[1], &stExtFrmInfo, s32MilliSec);
139 if (s32Ret != HI_SUCCESS) {
140 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_GetChnFrame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", s32Ret, s32VpssGrp,
141 as32VpssChn[1]);
142 continue;
143 }
144
145 s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[0], &stBaseFrmInfo, s32MilliSec);
146 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXT_RELEASE,
147 "Error(%#x),HI_MPI_VPSS_GetChnFrame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", s32Ret, s32VpssGrp,
148 as32VpssChn[0]);
149
150 if (HI_TRUE != bFirstFrm) {
151 s32Ret = SAMPLE_COMM_IVE_DmaImage(&stExtFrmInfo, &pstMd->astImg[s32CurIdx], bInstant);
152 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "SAMPLE_COMM_IVE_DmaImage fail,Error(%#x)\n",
153 s32Ret);
154 } else {
155 s32Ret = SAMPLE_COMM_IVE_DmaImage(&stExtFrmInfo, &pstMd->astImg[1 - s32CurIdx], bInstant);
156 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "SAMPLE_COMM_IVE_DmaImage fail,Error(%#x)\n",
157 s32Ret);
158
159 bFirstFrm = HI_FALSE;
160 goto CHANGE_IDX; // first frame just init reference frame
161 }
162
163 s32Ret =
164 HI_IVS_MD_Process(MdChn, &pstMd->astImg[s32CurIdx], &pstMd->astImg[1 - s32CurIdx], NULL, &pstMd->stBlob);
165 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "HI_IVS_MD_Process fail,Error(%#x)\n", s32Ret);
166 SAMPLE_COMM_IVE_BlobToRect(SAMPLE_COMM_IVE_CONVERT_64BIT_ADDR(IVE_CCBLOB_S, pstMd->stBlob.u64VirAddr),
167 &(pstMd->stRegion), IVE_RECT_NUM, SAMPLE_IVE_MD_AREA_THR_STEP, pstMdAttr->u32Width, pstMdAttr->u32Height,
168 stBaseFrmInfo.stVFrame.u32Width, stBaseFrmInfo.stVFrame.u32Height);
169
170 // Draw rect
171 s32Ret = SAMPLE_COMM_VGS_FillRect(&stBaseFrmInfo, &pstMd->stRegion, SAMPLE_IVE_MD_COLOR); // 0x0000FF00
172 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "SAMPLE_COMM_VGS_FillRect fail,Error(%#x)\n",
173 s32Ret);
174
175 s32Ret = HI_MPI_VO_SendFrame(voLayer, voChn, &stBaseFrmInfo, s32MilliSec);
176 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, BASE_RELEASE, "HI_MPI_VO_SendFrame fail,Error(%#x)\n", s32Ret);
177
178 CHANGE_IDX:
179 // Change reference and current frame index
180 s32CurIdx = 1 - s32CurIdx;
181
182 BASE_RELEASE:
183 s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp, as32VpssChn[0], &stBaseFrmInfo);
184 if (s32Ret != HI_SUCCESS) {
185 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n", s32Ret, s32VpssGrp,
186 as32VpssChn[0]);
187 }
188
189 EXT_RELEASE:
190 s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp, as32VpssChn[1], &stExtFrmInfo);
191 if (s32Ret != HI_SUCCESS) {
192 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n", s32Ret, s32VpssGrp,
193 as32VpssChn[1]);
194 }
195 }
196
197 // destroy
198 s32Ret = HI_IVS_MD_DestroyChn(MdChn);
199 if (s32Ret != HI_SUCCESS) {
200 SAMPLE_PRT("HI_IVS_MD_DestroyChn fail,Error(%#x)\n", s32Ret);
201 }
202
203 return HI_NULL;
204 }
205
SAMPLE_IVE_MdPause(HI_VOID)206 static HI_S32 SAMPLE_IVE_MdPause(HI_VOID)
207 {
208 printf("---------------press Enter key to exit!---------------\n");
209 if (s_bStopSignal == HI_TRUE) {
210 if (s_hMdThread != 0) {
211 pthread_join(s_hMdThread, HI_NULL);
212 s_hMdThread = 0;
213 }
214 SAMPLE_IVE_Md_Uninit(&(s_stMd));
215 (HI_VOID)memset_s(&s_stMd, sizeof(s_stMd), 0, sizeof(s_stMd));
216
217 SAMPLE_COMM_IVE_StopViVpssVencVo(&s_stViConfig, &s_stMdSwitch);
218 printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
219 return HI_FAILURE;
220 }
221 (HI_VOID)getchar();
222 if (s_bStopSignal == HI_TRUE) {
223 if (s_hMdThread != 0) {
224 pthread_join(s_hMdThread, HI_NULL);
225 s_hMdThread = 0;
226 }
227 SAMPLE_IVE_Md_Uninit(&(s_stMd));
228 (HI_VOID)memset_s(&s_stMd, sizeof(s_stMd), 0, sizeof(s_stMd));
229
230 SAMPLE_COMM_IVE_StopViVpssVencVo(&s_stViConfig, &s_stMdSwitch);
231 printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
232 return HI_FAILURE;
233 }
234 return HI_SUCCESS;
235 }
236
SAMPLE_IVE_Md(HI_VOID)237 HI_VOID SAMPLE_IVE_Md(HI_VOID)
238 {
239 SIZE_S stSize;
240 PIC_SIZE_E enSize = PIC_D1_PAL;
241 HI_S32 s32Ret = HI_SUCCESS;
242
243 (HI_VOID)memset_s(&s_stMd, sizeof(s_stMd), 0, sizeof(s_stMd));
244 /* step 1: start vi vpss venc vo */
245 s32Ret = SAMPLE_COMM_IVE_StartViVpssVencVo(&s_stViConfig, &s_stMdSwitch, &enSize);
246 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_MD_0, "Error(%#x),SAMPLE_COMM_IVE_StartViVpssVencVo failed!\n",
247 s32Ret);
248
249 enSize = PIC_D1_PAL;
250 s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSize, &stSize);
251 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_MD_0, "Error(%#x),SAMPLE_COMM_SYS_GetPicSize failed!\n", s32Ret);
252 /* step 2: Init Md */
253 s32Ret = SAMPLE_IVE_Md_Init(&s_stMd, stSize.u32Width, stSize.u32Height);
254 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_MD_0, " Error(%#x),SAMPLE_IVE_Md_Init failed!\n", s32Ret);
255 s_bStopSignal = HI_FALSE;
256 /* step 3: Create work thread */
257 s32Ret = prctl(PR_SET_NAME, "IVE_MdProc", 0, 0, 0);
258 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_MD_0, "thread set name failed!\n");
259 s32Ret = pthread_create(&s_hMdThread, 0, SAMPLE_IVE_MdProc, (HI_VOID *)&s_stMd);
260 SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, END_MD_0, "thread create failed!\n");
261
262 s32Ret = SAMPLE_IVE_MdPause();
263 SAMPLE_CHECK_EXPR_RET_VOID(s32Ret != HI_SUCCESS, "pause failed!\n");
264
265 s_bStopSignal = HI_TRUE;
266 pthread_join(s_hMdThread, HI_NULL);
267 s_hMdThread = 0;
268
269 SAMPLE_IVE_Md_Uninit(&(s_stMd));
270 (HI_VOID)memset_s(&s_stMd, sizeof(s_stMd), 0, sizeof(s_stMd));
271
272 END_MD_0:
273 s_bStopSignal = HI_TRUE;
274 s_hMdThread = 0;
275 SAMPLE_COMM_IVE_StopViVpssVencVo(&s_stViConfig, &s_stMdSwitch);
276 return;
277 }
278
279 /* function : Md sample signal handle */
SAMPLE_IVE_Md_HandleSig(HI_VOID)280 HI_VOID SAMPLE_IVE_Md_HandleSig(HI_VOID)
281 {
282 s_bStopSignal = HI_TRUE;
283 }
284