• 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 
16 #include <iostream>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 #include <csignal>
21 #include <unistd.h>
22 #include <pthread.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <sys/ioctl.h>
27 #include <sys/prctl.h>
28 
29 #include "hi_mipi_tx.h"
30 #include "sdk.h"
31 #include "sample_comm.h"
32 #include "ai_infer_process.h"
33 #include "tennis_detect.h"
34 #include "vgs_img.h"
35 #include "base_interface.h"
36 #include "posix_help.h"
37 #include "sample_media_ai.h"
38 #include "sample_media_opencv.h"
39 
40 using namespace std;
41 
42 static HI_BOOL s_bOpenCVProcessStopSignal = HI_FALSE;
43 static pthread_t g_openCVProcessThread = 0;
44 static int g_opencv = 0;
45 static AicMediaInfo g_aicTennisMediaInfo = { 0 };
46 static AiPlugLib g_tennisWorkPlug = {0};
47 static HI_CHAR tennisDetectThreadName[16] = {0};
48 
49 /* Set VI DEV information */
TennisViCfgSetDev(ViCfg * self,int devId,WDR_MODE_E wdrMode)50 static void TennisViCfgSetDev(ViCfg* self, int devId, WDR_MODE_E wdrMode)
51 {
52     HI_ASSERT(self);
53     HI_ASSERT((int)wdrMode < WDR_MODE_BUTT);
54 
55     self->astViInfo[0].stDevInfo.ViDev = devId;
56     self->astViInfo[0].stDevInfo.enWDRMode = wdrMode;
57 }
58 
59 /* Set up the VI channel */
TennisViCfgSetChn(ViCfg * self,int chnId,PIXEL_FORMAT_E pixFormat,VIDEO_FORMAT_E videoFormat,DYNAMIC_RANGE_E dynamicRange)60 static void TennisViCfgSetChn(ViCfg* self, int chnId, PIXEL_FORMAT_E pixFormat,
61     VIDEO_FORMAT_E videoFormat, DYNAMIC_RANGE_E dynamicRange)
62 {
63     HI_ASSERT(self);
64     HI_ASSERT((int)pixFormat < PIXEL_FORMAT_BUTT);
65     HI_ASSERT((int)videoFormat < VIDEO_FORMAT_BUTT);
66     HI_ASSERT((int)dynamicRange < DYNAMIC_RANGE_BUTT);
67 
68     self->astViInfo[0].stChnInfo.ViChn = chnId;
69     self->astViInfo[0].stChnInfo.enPixFormat = pixFormat;
70     self->astViInfo[0].stChnInfo.enVideoFormat = videoFormat;
71     self->astViInfo[0].stChnInfo.enDynamicRange = dynamicRange;
72 }
73 
TennisViPramCfg(HI_VOID)74 static HI_VOID TennisViPramCfg(HI_VOID)
75 {
76     ViCfgInit(&g_aicTennisMediaInfo.viCfg);
77     TennisViCfgSetDev(&g_aicTennisMediaInfo.viCfg, 0, WDR_MODE_NONE);
78     ViCfgSetPipe(&g_aicTennisMediaInfo.viCfg, 0, -1, -1, -1);
79     g_aicTennisMediaInfo.viCfg.astViInfo[0].stPipeInfo.enMastPipeMode = VI_OFFLINE_VPSS_OFFLINE;
80     TennisViCfgSetChn(&g_aicTennisMediaInfo.viCfg, 0, PIXEL_FORMAT_YVU_SEMIPLANAR_420,
81         VIDEO_FORMAT_LINEAR, DYNAMIC_RANGE_SDR8);
82     g_aicTennisMediaInfo.viCfg.astViInfo[0].stChnInfo.enCompressMode = COMPRESS_MODE_SEG;
83 }
84 
TennisStVbParamCfg(VbCfg * self)85 static HI_VOID TennisStVbParamCfg(VbCfg *self)
86 {
87     memset_s(&g_aicTennisMediaInfo.vbCfg, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
88     // 2: The number of buffer pools that can be accommodated in the entire system
89     self->u32MaxPoolCnt              = 2;
90 
91     /* get picture buffer size */
92     g_aicTennisMediaInfo.u32BlkSize = COMMON_GetPicBufferSize(g_aicTennisMediaInfo.stSize.u32Width,
93         g_aicTennisMediaInfo.stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_SEG, DEFAULT_ALIGN);
94     self->astCommPool[0].u64BlkSize  = g_aicTennisMediaInfo.u32BlkSize;
95     // 10: Number of cache blocks per cache pool. Value range: (0, 10240]
96     self->astCommPool[0].u32BlkCnt   = 10;
97 
98     /* get raw buffer size */
99     g_aicTennisMediaInfo.u32BlkSize = VI_GetRawBufferSize(g_aicTennisMediaInfo.stSize.u32Width,
100         g_aicTennisMediaInfo.stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_16BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
101     self->astCommPool[1].u64BlkSize  = g_aicTennisMediaInfo.u32BlkSize;
102     // 4: Number of cache blocks per cache pool. Value range: (0, 10240]
103     self->astCommPool[1].u32BlkCnt   = 4;
104 }
105 
TennisVpssParamCfg(HI_VOID)106 static HI_VOID TennisVpssParamCfg(HI_VOID)
107 {
108     VpssCfgInit(&g_aicTennisMediaInfo.vpssCfg);
109     VpssCfgSetGrp(&g_aicTennisMediaInfo.vpssCfg, 0, NULL,
110         g_aicTennisMediaInfo.stSize.u32Width, g_aicTennisMediaInfo.stSize.u32Width);
111     g_aicTennisMediaInfo.vpssCfg.grpAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
112     // 1920:AICSTART_VI_OUTWIDTH, 1080: AICSTART_VI_OUTHEIGHT
113     VpssCfgAddChn(&g_aicTennisMediaInfo.vpssCfg, 1, NULL, 1920, 1080);
114     HI_ASSERT(!g_aicTennisMediaInfo.viSess);
115 }
116 
TennisStVoParamCfg(VoCfg * self)117 static HI_VOID TennisStVoParamCfg(VoCfg *self)
118 {
119     SAMPLE_COMM_VO_GetDefConfig(self);
120     self->enDstDynamicRange = DYNAMIC_RANGE_SDR8;
121 
122     self->enVoIntfType = VO_INTF_MIPI; /* set VO int type */
123     self->enIntfSync = VO_OUTPUT_USER; /* set VO output information */
124 
125     self->enPicSize = g_aicTennisMediaInfo.enPicSize;
126 }
127 
TennisDetectAiProcess(VIDEO_FRAME_INFO_S frm,VO_LAYER voLayer,VO_CHN voChn)128 static HI_VOID TennisDetectAiProcess(VIDEO_FRAME_INFO_S frm, VO_LAYER voLayer, VO_CHN voChn)
129 {
130     int ret;
131     tennis_detect opencv;
132     if (GetCfgBool("tennis_detect_switch:support_tennis_detect", true)) {
133         if (g_tennisWorkPlug.model == 0) {
134             ret = opencv.TennisDetectLoad(&g_tennisWorkPlug.model);
135             if (ret < 0) {
136                 g_tennisWorkPlug.model = 0;
137                 SAMPLE_CHECK_EXPR_GOTO(ret < 0, TENNIS_RELEASE, "TennisDetectLoad err, ret=%#x\n", ret);
138             }
139         }
140 
141         VIDEO_FRAME_INFO_S calFrm;
142         ret = MppFrmResize(&frm, &calFrm, 640, 480); // 640: FRM_WIDTH, 480: FRM_HEIGHT
143         ret = opencv.TennisDetectCal(g_tennisWorkPlug.model, &calFrm, &frm);
144         SAMPLE_CHECK_EXPR_GOTO(ret < 0, TENNIS_RELEASE, "TennisDetectCal err, ret=%#x\n", ret);
145 
146         ret = HI_MPI_VO_SendFrame(voLayer, voChn, &frm, 0);
147         SAMPLE_CHECK_EXPR_GOTO(ret != HI_SUCCESS, TENNIS_RELEASE,
148             "HI_MPI_VO_SendFrame err, ret=%#x\n", ret);
149         MppFrmDestroy(&calFrm);
150     }
151 
152     TENNIS_RELEASE:
153         ret = HI_MPI_VPSS_ReleaseChnFrame(g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0, &frm);
154         if (ret != HI_SUCCESS) {
155             SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n",
156                 ret, g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0);
157         }
158 }
159 
GetVpssChnFrameTennisDetect(HI_VOID * arg)160 static HI_VOID* GetVpssChnFrameTennisDetect(HI_VOID* arg)
161 {
162     int ret;
163     VIDEO_FRAME_INFO_S frm;
164     HI_S32 s32MilliSec = 2000;
165     VO_LAYER voLayer = 0;
166     VO_CHN voChn = 0;
167 
168     SAMPLE_PRT("vpssGrp:%d, vpssChn0:%d\n", g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0);
169 
170     while (HI_FALSE == s_bOpenCVProcessStopSignal) {
171         ret = HI_MPI_VPSS_GetChnFrame(g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0, &frm, s32MilliSec);
172         if (ret != 0) {
173             SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame FAIL, err=%#x, grp=%d, chn=%d\n",
174                 ret, g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0);
175             ret = HI_MPI_VPSS_ReleaseChnFrame(g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0, &frm);
176             if (ret != HI_SUCCESS) {
177                 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n",
178                     ret, g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0);
179             }
180             continue;
181         }
182         SAMPLE_PRT("get vpss frame success, weight:%d, height:%d\n", frm.stVFrame.u32Width, frm.stVFrame.u32Height);
183 
184         if (g_opencv == 0) {
185             ConfBaseInit("./sample_ai.conf");
186             g_opencv++;
187         }
188         TennisDetectAiProcess(frm, voLayer, voChn);
189     }
190 
191     return HI_NULL;
192 }
193 
PauseDoUnloadTennisModel(HI_VOID)194 static HI_VOID PauseDoUnloadTennisModel(HI_VOID)
195 {
196     if (GetCfgBool("tennis_detect_switch:support_tennis_detect", true)) {
197         memset_s(&g_tennisWorkPlug, sizeof(g_tennisWorkPlug), 0x00, sizeof(g_tennisWorkPlug));
198         ConfBaseExt();
199         SAMPLE_PRT("tennis detect exit success\n");
200         g_opencv = 0;
201     }
202 }
203 
TennisDetectAiThreadProcess(HI_VOID)204 static HI_S32 TennisDetectAiThreadProcess(HI_VOID)
205 {
206     HI_S32 s32Ret;
207     if (snprintf_s(tennisDetectThreadName, sizeof(tennisDetectThreadName),
208         sizeof(tennisDetectThreadName) - 1, "OpencvProcess") < 0) {
209         HI_ASSERT(0);
210     }
211     prctl(PR_SET_NAME, (unsigned long)tennisDetectThreadName, 0, 0, 0);
212     s32Ret = pthread_create(&g_openCVProcessThread, NULL, GetVpssChnFrameTennisDetect, NULL);
213 
214     return s32Ret;
215 }
216 
217 /*
218  * Display the data collected by sensor to LCD screen
219  * VI->VPSS->VO->MIPI
220  */
SAMPLE_MEDIA_TENNIS_DETECT(HI_VOID)221 HI_S32 sample_media_opencv::SAMPLE_MEDIA_TENNIS_DETECT(HI_VOID)
222 {
223     HI_S32 s32Ret;
224     HI_S32 fd = 0;
225 
226     /* config vi */
227     TennisViPramCfg();
228 
229     /* get picture size */
230     s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(g_aicTennisMediaInfo.viCfg.astViInfo[0].stSnsInfo.enSnsType,
231         &g_aicTennisMediaInfo.enPicSize);
232     SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "get pic size by sensor fail, s32Ret=%#x\n", s32Ret);
233 
234     /* get picture size(w*h), according enPicSize */
235     s32Ret = SAMPLE_COMM_SYS_GetPicSize(g_aicTennisMediaInfo.enPicSize, &g_aicTennisMediaInfo.stSize);
236     SAMPLE_PRT("AIC: snsMaxSize=%ux%u\n", g_aicTennisMediaInfo.stSize.u32Width, g_aicTennisMediaInfo.stSize.u32Height);
237     SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "get picture size failed, s32Ret=%#x\n", s32Ret);
238 
239     /* config vb */
240     TennisStVbParamCfg(&g_aicTennisMediaInfo.vbCfg);
241 
242     /* vb init & MPI system init */
243     s32Ret = SAMPLE_COMM_SYS_Init(&g_aicTennisMediaInfo.vbCfg);
244     SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "system init failed, s32Ret=%#x\n", s32Ret);
245 
246     /* set VO config to mipi, get mipi device */
247     s32Ret = SAMPLE_VO_CONFIG_MIPI(&fd);
248     SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT, "CONFIG MIPI FAIL.s32Ret:0x%x\n", s32Ret);
249 
250     /* config vpss */
251     TennisVpssParamCfg();
252     s32Ret = ViVpssCreate(&g_aicTennisMediaInfo.viSess, &g_aicTennisMediaInfo.viCfg, &g_aicTennisMediaInfo.vpssCfg);
253     SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT1, "ViVpss Sess create FAIL, ret=%#x\n", s32Ret);
254     g_aicTennisMediaInfo.vpssGrp = 0;
255     g_aicTennisMediaInfo.vpssChn0 = 1;
256 
257     /* config vo */
258     TennisStVoParamCfg(&g_aicTennisMediaInfo.voCfg);
259 
260     /* start vo */
261     s32Ret = SampleCommVoStartMipi(&g_aicTennisMediaInfo.voCfg);
262     SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT1, "start vo FAIL. s32Ret: 0x%x\n", s32Ret);
263 
264     /* vpss bind vo */
265     s32Ret = SAMPLE_COMM_VPSS_Bind_VO(g_aicTennisMediaInfo.vpssGrp,
266         g_aicTennisMediaInfo.vpssChn0, g_aicTennisMediaInfo.voCfg.VoDev, 0);
267     SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT2, "vo bind vpss FAIL. s32Ret: 0x%x\n", s32Ret);
268     SAMPLE_PRT("vpssGrp:%d, vpssChn:%d\n", g_aicTennisMediaInfo.vpssGrp, g_aicTennisMediaInfo.vpssChn0);
269 
270     /* create work thread to run ai */
271     s32Ret = TennisDetectAiThreadProcess();
272     SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "ai proccess thread creat fail:%s\n", strerror(s32Ret));
273 
274     PAUSE();
275     s_bOpenCVProcessStopSignal = HI_TRUE;
276     pthread_join(g_openCVProcessThread, nullptr);
277     g_openCVProcessThread = 0;
278     PauseDoUnloadTennisModel();
279 
280     SAMPLE_COMM_VPSS_UnBind_VO(g_aicTennisMediaInfo.vpssGrp,
281         g_aicTennisMediaInfo.vpssChn0, g_aicTennisMediaInfo.voCfg.VoDev, 0);
282     SAMPLE_VO_DISABLE_MIPITx(fd);
283     SampleCloseMipiTxFd(fd);
284     system("echo 0 > /sys/class/gpio/gpio55/value");
285 
286 EXIT2:
287     SAMPLE_COMM_VO_StopVO(&g_aicTennisMediaInfo.voCfg);
288 EXIT1:
289     VpssStop(&g_aicTennisMediaInfo.vpssCfg);
290     SAMPLE_COMM_VI_UnBind_VPSS(g_aicTennisMediaInfo.viCfg.astViInfo[0].stPipeInfo.aPipe[0],
291         g_aicTennisMediaInfo.viCfg.astViInfo[0].stChnInfo.ViChn, g_aicTennisMediaInfo.vpssGrp);
292     ViStop(&g_aicTennisMediaInfo.viCfg);
293     free(g_aicTennisMediaInfo.viSess);
294 EXIT:
295     SAMPLE_COMM_SYS_Exit();
296     return s32Ret;
297 }