diff --git a/vendor/.gitkeep b/vendor/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/Makefile b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..5c0d0b328341f5ab30d765ceaea25a4d8476f267 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/Makefile @@ -0,0 +1,44 @@ +# 编译所需的公共文件 +include ../mk.param + +# 编译后生成的可执行文件名 +TARGET := main + +# 编译此工程需要包含的头文件 +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR)/ +CFLAGS += -I$(SDK_SAMPLE_COMMON_DIR)/ +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR)/svp_npu + +# 编译此工程需要依赖的.c或.cpp文件 +SMP_SRCS := $(SDK_SAMPLE_COMMON_DIR)/sample_comm_sys.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_ipc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_isp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vi.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vo.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_mipi_tx.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vpss.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/loadbmp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vdec.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_venc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_init.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_exit.c +SMP_SRCS += $(wildcard $(SVP_COMMON_DIR)/*.c) +SMP_SRCS += $(FACE_DETECTION_SAMPLE_DIR)/face_detection.c + +# 编译此工程需要包含的库和宏 +CFLAGS += -O3 -g -Wall -DUSE_USB_CAMERA +CFLAGS += -fstack-protector-strong + +# 根据实际的类型设置,可以用set_sensor脚本设置 +SENSOR0_TYPE = -DSENSOR0_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR1_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR2_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR3_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT + +CFLAGS += $(SENSOR0_TYPE) +CFLAGS += $(SENSOR1_TYPE) +CFLAGS += $(SENSOR2_TYPE) +CFLAGS += $(SENSOR3_TYPE) +# 编译工程所需的mk文件 + +include ../sdk_linux.mk diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/README.md b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/README.md new file mode 100755 index 0000000000000000000000000000000000000000..b9c21e3af9f691dce28e010a8e0a26fc3754ae87 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/README.md @@ -0,0 +1,128 @@ +## 2.5、face_detection 操作指导 + +### 2.5.1、face_detection 程序简介 + +* face_detection sample基于SS928V100平台开发,以EulerPi套件为例,face_detection sample是通过USB Camera,将采集到的图片送到人脸检测模型中进行推理,当检测到人脸时,会在人脸区域画出矩形框,并通过外接HDMI线实时的显示在外接显示屏上。 +* face_detection 案例主要是使用pytorch框架,基于YoloV8网络,使用widerface、FDDB、UFDD等开源数据集,共1.3万多张训练出来在强光、逆光、暗光下的人脸检测模型。 + + + +### 2.5.2、目录 + +```shell +pegasus/vendor/cust/demo/face_detection +|── data # 模型文件 +|── Makefile # 编译脚本 +└── face_detection.c # face_detection sample业务代码 +``` + +![image-20250919144926220](pic/image-20250919144926220.png) + +### 2.5.3、编译 + +* **注意:在编译cust的demo之前,请确保你已经按照[patch介绍中的步骤](../../README.md#4patch介绍)把补丁打入海思SDK的sample目录下了**。 + +* 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 + +* 步骤2:使用Makefile的方式进行单编 + +* 在Ubuntu的命令行终端,分步执行下面的命令,单编 face_detection sample + + ``` + cd pegasus/vendor/cust/demo/face_detection + + make clean && make + ``` + + ![image-20250919145314492](pic/image-20250919145314492.png) + + * 在face_detection目录下,生成一个名为 face_detection 的 可执行文件,如下图所示: + + ![image-20250919145335685](pic/image-20250919145335685.png) + +### 2.5.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +* 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +image-20221114150205685 + +* 步骤1:将编译后生成的可执行文件拷贝到SD卡中。 + +![image-20250919145846452](pic/image-20250919145846452.png) + +* 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +image-20250210161601541 + +* 在开发板的终端,执行下面的命令进行SD卡的挂载 + * 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +* 挂载成功后,如下图所示: + +![image-20250919150059493](pic/image-20250919150059493.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +* 首先需要自己准备一根网线 +* 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +* 步骤2:将编译后生成的可执行文件拷贝到Windows的nfs共享路径下 + +![image-20250919150131086](pic/image-20250919150131086.png) + +* 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + * 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + + +``` +ifconfig eth0 192.168.100.100 +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20250919150233049](pic/image-20250919150233049.png) + +### 2.5.5、硬件连接 + +* 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image-20250213112932380](pic/image-20250213112932380.png) + +* 将USB 摄像头接在EulerPi开发板的USB接口上。 + +image-20250919150630870 + +### 2.5.6、功能验证 + +* 在开发板的终端执行下面的命令,运行可执行文件 + +``` +cd /mnt + +chmod +x face_detection + +./face_detection +``` + +![image-20250919150812107](pic/image-20250919150812107.png) + +* 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +image-20250210170027454 + +* 如果您看到的现象和下图现象不一致,可以确认一下USB涉嫌头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659.png) + +* 正常情况下,我们会在外接显示屏上看到人脸的区域被框出来,且在比较黑暗或者强逆光条件下,也能比较好的检测到人脸。![image-20250919151605632](pic/image-20250919151605632.png) + +* 敲两下回车即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310.png) + diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/data/model/face_detection.om b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/data/model/face_detection.om new file mode 100755 index 0000000000000000000000000000000000000000..4765828d501e8d424ae023e6cedff0bb4cf24a5e Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/data/model/face_detection.om differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/face_detection.c b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/face_detection.c new file mode 100755 index 0000000000000000000000000000000000000000..44779cbca233b4d0c63fb2f5551a0de4c535458e --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/face_detection.c @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "svp_acl.h" +#include "svp_acl_rt.h" +#include "svp_acl_ext.h" +#include "sdk_module_init.h" +#include "sample_common_svp.h" +#include "sample_common_svp_npu.h" +#include "sample_common_svp_npu_model.h" + +/* 新增v4l2相关头文件 */ +#include // 文件控制 +#include // 错误处理 +#include // POSIX API +#include // IO控制 +#include // 内存映射 +#include // select复用 +#include // v4l2核心 + +#define SAMPLE_SVP_NPU_RESNET50_INPUT_FILE_NUM 1 +#define SAMPLE_SVP_NPU_LSTM_INPUT_FILE_NUM 4 +#define SAMPLE_SVP_NPU_SHAERD_WORK_BUF_NUM 1 +#define SAMPLE_SVP_NPU_YOLO_TYPE_NUM 12 +#define SAMPLE_SVP_NPU_YOLO_THRESHOLD_NUM 1 + +#define SAMPLE_SVP_NPU_PATH_LEN 0x100 +static td_bool g_svp_npu_terminate_signal = TD_FALSE; +static td_s32 g_svp_npu_dev_id = 0; +static sample_svp_npu_task_info g_svp_npu_task[SAMPLE_SVP_NPU_MAX_TASK_NUM] = {0}; +static sample_svp_npu_shared_work_buf g_svp_npu_shared_work_buf[SAMPLE_SVP_NPU_SHAERD_WORK_BUF_NUM] = {0}; + +static sample_svp_npu_threshold g_svp_npu_yolo_threshold[SAMPLE_SVP_NPU_YOLO_TYPE_NUM] = { + {0.9, 0.15, 1.0, 1.0, "rpn_data"}, // yolov8 +}; + +static sample_svp_npu_roi_info g_svp_npu_yolo_roi_info[SAMPLE_SVP_NPU_YOLO_TYPE_NUM] = { + {"output0", "output0_"}, // yolov8 +}; + +static ot_sample_svp_rect_info g_svp_npu_rect_info = {0}; +static td_bool g_svp_npu_thread_stop = TD_FALSE; +static pthread_t g_svp_npu_thread = 0; +static sample_vo_cfg g_svp_npu_vo_cfg = { 0 }; +static pthread_t g_svp_npu_vdec_thread = 0; +static ot_vb_pool_info g_svp_npu_vb_pool_info; +static td_void *g_svp_npu_vb_virt_addr = TD_NULL; + +static ot_sample_svp_media_cfg g_svp_npu_media_cfg = { + .svp_switch = {TD_FALSE, TD_TRUE}, + .pic_type = {PIC_1080P, PIC_CIF}, + .chn_num = OT_SVP_MAX_VPSS_CHN_NUM, +}; + +static sample_vdec_attr g_svp_npu_vdec_cfg = { + .type = OT_PT_MJPEG, + .mode = OT_VDEC_SEND_MODE_FRAME, + .width = FHD_WIDTH, + .height = FHD_HEIGHT, + .sample_vdec_picture.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420, /* 420:pixel_format */ + .sample_vdec_picture.alpha = 0, /* 0:alpha */ + .display_frame_num = 2, /* 2:display_frame_num */ + .frame_buf_cnt = 5, /* 5:2+2+1 */ +}; + +static vdec_thread_param g_svp_npu_vdec_param = { + .chn_id = 0, + + .v4l2_device = "/dev/video0", // 摄像头设备 + .width = FHD_WIDTH, // 采集分辨率宽 + .height = FHD_HEIGHT, // 采集分辨率高 + .pixel_format = V4L2_PIX_FMT_MJPEG, // MJPEG格式 + + .type = OT_PT_MJPEG, + .stream_mode = OT_VDEC_SEND_MODE_FRAME, + .interval_time = 1000, /* 1000:interval_time */ + .pts_init = 0, + .pts_increase = 0, + .e_thread_ctrl = THREAD_CTRL_START, + .circle_send = TD_TRUE, + .milli_sec = 0, + .min_buf_size = (FHD_WIDTH * FHD_HEIGHT * 3) >> 1, /* 3:chn_size */ + .fps = 30, +}; + +static td_void sample_svp_npu_acl_terminate(td_void) +{ + if (g_svp_npu_terminate_signal == TD_TRUE) { + printf("\033[0;31mprogram termination abnormally!\033[0;39m\n"); + } +} + +/* function : svp npu signal handle */ +td_void sample_svp_npu_acl_handle_sig(td_void) +{ + g_svp_npu_terminate_signal = TD_TRUE; +} + +static td_void sample_svp_npu_acl_deinit(td_void) +{ + svp_acl_error ret; + + ret = svp_acl_rt_reset_device(g_svp_npu_dev_id); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("reset device fail\n"); + } + sample_svp_trace_info("end to reset device is %d\n", g_svp_npu_dev_id); + + ret = svp_acl_finalize(); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("finalize acl fail\n"); + } + sample_svp_trace_info("end to finalize acl\n"); + (td_void)sample_common_svp_check_sys_exit(); +} + +static td_s32 sample_svp_npu_acl_init(const td_char *acl_config_path, td_bool vi_en) +{ + /* svp acl init */ + svp_acl_rt_run_mode run_mode; + svp_acl_error ret; + td_bool is_mpi_init; + + is_mpi_init = sample_common_svp_check_sys_init(vi_en); + sample_svp_check_exps_return(is_mpi_init != TD_TRUE, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "mpi init failed!\n"); + + ret = svp_acl_init(acl_config_path); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "acl init failed!\n"); + + sample_svp_trace_info("svp acl init success!\n"); + + /* open device */ + ret = svp_acl_rt_set_device(g_svp_npu_dev_id); + if (ret != SVP_ACL_SUCCESS) { + (td_void)svp_acl_finalize(); + sample_svp_trace_err("svp acl open device %d failed!\n", g_svp_npu_dev_id); + return TD_FAILURE; + } + sample_svp_trace_info("open device %d success!\n", g_svp_npu_dev_id); + + /* get run mode */ + ret = svp_acl_rt_get_run_mode(&run_mode); + if ((ret != SVP_ACL_SUCCESS) || (run_mode != SVP_ACL_DEVICE)) { + (td_void)svp_acl_rt_reset_device(g_svp_npu_dev_id); + (td_void)svp_acl_finalize(); + sample_svp_trace_err("acl get run mode failed!\n"); + return TD_FAILURE; + } + sample_svp_trace_info("get run mode success!\n"); + + return TD_SUCCESS; +} + +static td_s32 sample_svp_npu_acl_dataset_init(td_u32 task_idx) +{ + td_s32 ret = sample_common_svp_npu_create_input(&g_svp_npu_task[task_idx]); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "create input failed!\n"); + + ret = sample_common_svp_npu_create_output(&g_svp_npu_task[task_idx]); + if (ret != TD_SUCCESS) { + sample_common_svp_npu_destroy_input(&g_svp_npu_task[task_idx]); + sample_svp_trace_err("execute create output fail.\n"); + return TD_FAILURE; + } + return TD_SUCCESS; +} + +static td_void sample_svp_npu_acl_dataset_deinit(td_u32 task_idx) +{ + (td_void)sample_common_svp_npu_destroy_input(&g_svp_npu_task[task_idx]); + (td_void)sample_common_svp_npu_destroy_output(&g_svp_npu_task[task_idx]); +} + +static td_void sample_svp_npu_acl_deinit_task(td_u32 task_num, td_u32 shared_work_buf_idx) +{ + td_u32 task_idx; + + for (task_idx = 0; task_idx < task_num; task_idx++) { + (td_void)sample_common_svp_npu_destroy_work_buf(&g_svp_npu_task[task_idx]); + (td_void)sample_common_svp_npu_destroy_task_buf(&g_svp_npu_task[task_idx]); + (td_void)sample_svp_npu_acl_dataset_deinit(task_idx); + (td_void)memset_s(&g_svp_npu_task[task_idx], sizeof(sample_svp_npu_task_cfg), 0, + sizeof(sample_svp_npu_task_cfg)); + } + if (g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr != TD_NULL) { + (td_void)svp_acl_rt_free(g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr); + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr = TD_NULL; + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size = 0; + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_stride = 0; + } +} + +static td_s32 sample_svp_npu_acl_create_shared_work_buf(td_u32 task_num, td_u32 shared_work_buf_idx) +{ + td_u32 task_idx; + td_u32 work_buf_size; + td_u32 work_buf_stride; + td_s32 ret; + + for (task_idx = 0; task_idx < task_num; task_idx++) { + ret = sample_common_svp_npu_get_work_buf_info(&g_svp_npu_task[task_idx], &work_buf_size, &work_buf_stride); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th task work buf info failed!\n", task_idx); + + if (g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size < work_buf_size) { + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size = work_buf_size; + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_stride = work_buf_stride; + } + } + ret = svp_acl_rt_malloc_cached(&g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr, + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size, SVP_ACL_MEM_MALLOC_NORMAL_ONLY); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "malloc %u-th shared work buf failed!\n", shared_work_buf_idx); + + (td_void)svp_acl_rt_mem_flush(g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr, + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size); + return TD_SUCCESS; +} + +static td_s32 sample_svp_npu_acl_init_task(td_u32 task_num, td_bool is_share_work_buf, + td_u32 shared_work_buf_idx) +{ + td_u32 task_idx; + td_s32 ret; + + if (is_share_work_buf == TD_TRUE) { + ret = sample_svp_npu_acl_create_shared_work_buf(task_num, shared_work_buf_idx); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "create shared work buf failed!\n"); + } + + for (task_idx = 0; task_idx < task_num; task_idx++) { + ret = sample_svp_npu_acl_dataset_init(task_idx); + if (ret != TD_SUCCESS) { + goto task_init_end_0; + } + ret = sample_common_svp_npu_create_task_buf(&g_svp_npu_task[task_idx]); + if (ret != TD_SUCCESS) { + sample_svp_trace_err("create task buf failed.\n"); + goto task_init_end_0; + } + if (is_share_work_buf == TD_FALSE) { + ret = sample_common_svp_npu_create_work_buf(&g_svp_npu_task[task_idx]); + } else { + /* if all tasks are on the same stream, work buf can be shared */ + ret = sample_common_svp_npu_share_work_buf(&g_svp_npu_shared_work_buf[shared_work_buf_idx], + &g_svp_npu_task[task_idx]); + } + if (ret != TD_SUCCESS) { + sample_svp_trace_err("create work buf failed.\n"); + goto task_init_end_0; + } + } + return TD_SUCCESS; + +task_init_end_0: + (td_void)sample_svp_npu_acl_deinit_task(task_num, shared_work_buf_idx); + return ret; +} + +static td_s32 sample_svp_npu_acl_frame_proc(const ot_video_frame_info *ext_frame, + const ot_video_frame_info *base_frame, td_void *args) +{ + td_s32 ret; + td_void *virt_addr = TD_NULL; + sample_svp_npu_detection_info *detection_info = TD_NULL; + sample_svp_npu_thread_args *thread_args = (sample_svp_npu_thread_args *)args; + td_u32 size = (td_u32)(ext_frame->video_frame.height * ext_frame->video_frame.stride[0] * + SAMPLE_SVP_NPU_IMG_THREE_CHN / SAMPLE_SVP_NPU_DOUBLE); + + virt_addr = g_svp_npu_vb_virt_addr + + (ext_frame->video_frame.phys_addr[0] - g_svp_npu_vb_pool_info.pool_phy_addr); + ret = sample_common_svp_npu_update_input_data_buffer_info(virt_addr, size, + ext_frame->video_frame.stride[0], 0, &g_svp_npu_task[0]); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "update data buffer failed!\n"); + + ret = sample_common_svp_npu_model_execute(&g_svp_npu_task[0]); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "model execute failed!\n"); + + if (thread_args->model_name == SAMPLE_SVP_NPU_RFCN || thread_args->model_name == SAMPLE_SVP_NPU_YOLO) { + detection_info = thread_args->detection_info; + if (detection_info->is_cpu_rpn == TD_FALSE) { + ret = sample_common_svp_npu_roi_to_rect(&g_svp_npu_task[0], detection_info, ext_frame, base_frame, + &g_svp_npu_rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "roi to rect failed!\n"); + } else { + ret = sample_common_svp_npu_roi_to_rect_cpu(&g_svp_npu_task[0], detection_info, ext_frame, base_frame, + &g_svp_npu_rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "roi to rect failed!\n"); + } + ret = sample_common_svp_vgs_fill_rect(base_frame, &g_svp_npu_rect_info, SAMPLE_SVP_NPU_RECT_COLOR); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "vgs fill rect failed!\n"); + for (int i = 0; i < g_svp_npu_rect_info.num; i++) { + printf("score:%lf, class_id:%d\r\n", g_svp_npu_rect_info.rect[i].score, + g_svp_npu_rect_info.rect[i].class_id); + } + } + return ret; +} + +static td_s32 sample_svp_npu_acl_vb_map(td_u32 vb_pool_idx) +{ + td_s32 ret; + + if (g_svp_npu_vb_virt_addr == TD_NULL) { + ret = ss_mpi_vb_get_pool_info(g_svp_npu_media_cfg.vb_pool[vb_pool_idx], &g_svp_npu_vb_pool_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get pool info failed!\n"); + g_svp_npu_vb_virt_addr = ss_mpi_sys_mmap(g_svp_npu_vb_pool_info.pool_phy_addr, + g_svp_npu_vb_pool_info.pool_size); + sample_svp_check_exps_return(g_svp_npu_vb_virt_addr == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "map vb pool failed!\n"); + } + return TD_SUCCESS; +} + +static td_void *sample_svp_npu_acl_vdec_to_vo(td_void *args) +{ + td_s32 ret; + ot_video_frame_info base_frame; + ot_video_frame_info ext_frame; + const td_s32 milli_sec = SAMPLE_SVP_NPU_MILLIC_SEC; + const ot_vo_layer vo_layer = 0; + const ot_vo_chn vo_chn = 0; + const td_s32 vpss_grp = 0; + td_s32 vpss_chn[] = { OT_VPSS_CHN0, OT_VPSS_CHN1 }; + td_u32 size; + td_u32 stride; + td_u8 *data = TD_NULL; + + (td_void)prctl(PR_SET_NAME, "svp_npu_vdec_to_vo", 0, 0, 0); + + ret = svp_acl_rt_set_device(g_svp_npu_dev_id); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "open device failed!\n"); + + ret = sample_svp_npu_acl_vb_map(OT_VPSS_CHN1); + sample_svp_check_exps_goto(ret != TD_SUCCESS, fail_0, SAMPLE_SVP_ERR_LEVEL_ERROR, "map vb pool failed!\n"); + + ret = sample_common_svp_npu_get_input_data_buffer_info(&g_svp_npu_task[0], 0, &data, &size, &stride); + sample_svp_check_exps_goto(ret != TD_SUCCESS, fail_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),get_input_data_buffer_info failed!\n", ret); + + while (g_svp_npu_thread_stop == TD_FALSE) { + ret = ss_mpi_vpss_get_chn_frame(vpss_grp, vpss_chn[1], &ext_frame, milli_sec); + sample_svp_check_exps_continue(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),ss_mpi_vpss_get_chn_frame failed, vpss_grp(%d), vpss_chn(%d)!\n", ret, vpss_grp, vpss_chn[1]); + + ret = ss_mpi_vpss_get_chn_frame(vpss_grp, vpss_chn[0], &base_frame, milli_sec); + sample_svp_check_exps_goto(ret != TD_SUCCESS, ext_release, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),ss_mpi_vpss_get_chn_frame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", ret, vpss_grp, vpss_chn[0]); + + ret = sample_svp_npu_acl_frame_proc(&ext_frame, &base_frame, args); + sample_svp_check_exps_goto(ret != TD_SUCCESS, base_release, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_svp_npu_acl_frame_proc failed!\n", ret); + + ret = sample_common_svp_venc_vo_send_stream(&g_svp_npu_media_cfg.svp_switch, 0, vo_layer, vo_chn, &base_frame); + sample_svp_check_exps_goto(ret != TD_SUCCESS, base_release, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_venc_vo_send_stream failed!\n", ret); +base_release: + ret = ss_mpi_vpss_release_chn_frame(vpss_grp, vpss_chn[0], &base_frame); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),release_frame failed,grp(%d) chn(%d)!\n", ret, vpss_grp, vpss_chn[0]); +ext_release: + ret = ss_mpi_vpss_release_chn_frame(vpss_grp, vpss_chn[1], &ext_frame); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),release_frame failed,grp(%d) chn(%d)!\n", ret, vpss_grp, vpss_chn[1]); + } + ret = sample_common_svp_npu_update_input_data_buffer_info(data, size, stride, 0, &g_svp_npu_task[0]); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, "update buffer failed!\n"); +fail_1: + (td_void)ss_mpi_sys_munmap(g_svp_npu_vb_virt_addr, g_svp_npu_vb_pool_info.pool_size); +fail_0: + (td_void)svp_acl_rt_reset_device(g_svp_npu_dev_id); + return TD_NULL; +} + +static td_void sample_svp_npu_acl_pause(td_void) +{ + printf("---------------press Enter key to exit!---------------\n"); + if (g_svp_npu_terminate_signal == TD_TRUE) { + return; + } + (td_void)getchar(); + if (g_svp_npu_terminate_signal == TD_TRUE) { + return; + } +} + +static td_void sample_svp_npu_acl_set_task_info(td_u32 model_idx) +{ + g_svp_npu_task[0].cfg.max_batch_num = 1; + g_svp_npu_task[0].cfg.dynamic_batch_num = 1; + g_svp_npu_task[0].cfg.total_t = 0; + g_svp_npu_task[0].cfg.is_cached = TD_TRUE; + g_svp_npu_task[0].cfg.model_idx = model_idx; +} + +static td_void sample_svp_npu_acl_set_detection_info(sample_svp_npu_detection_info *detection_info, td_u32 index, + td_bool is_cpu_rpn) +{ + detection_info->num_name = g_svp_npu_yolo_roi_info[index].roi_num_name; + detection_info->roi_name = g_svp_npu_yolo_roi_info[index].roi_class_name; + detection_info->has_background = TD_FALSE; + detection_info->is_cpu_rpn = is_cpu_rpn; + detection_info->idx = index; + /* use PIC_BUTT to be a flag, get the input resolution form om */ + g_svp_npu_media_cfg.pic_type[1] = PIC_BUTT; + g_svp_npu_terminate_signal = TD_FALSE; +} + +/* function : show the sample of yolo. RPN processed by npu */ +td_void sample_face_detection(void) +{ + td_s32 ret; + const td_u32 model_idx = 0; + const td_char *om_model_path = "./data/model/face_detection.om"; + sample_svp_npu_detection_info detection_info = {0}; + sample_svp_npu_thread_args args = {SAMPLE_SVP_NPU_YOLO, &detection_info}; + + sample_svp_npu_acl_set_detection_info(&detection_info, 0, TD_FALSE); + + if (g_svp_npu_terminate_signal == TD_FALSE) { + /* init acl */ + ret = sample_svp_npu_acl_init(TD_NULL, TD_FALSE); + sample_svp_check_exps_return_void(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, "init failed!\n"); + + /* load model */ + ret = sample_common_svp_npu_load_model(om_model_path, model_idx, TD_FALSE); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "load model failed!\n"); + + /* get input resolution */ + ret = sample_common_svp_npu_get_input_resolution(model_idx, 0, &g_svp_npu_media_cfg.pic_size[1]); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "load model failed!\n"); + + /* start vdec vpss venc vo */ + ret = sample_common_svp_create_vb_start_vdec_vpss_vo(&g_svp_npu_vdec_cfg, &g_svp_npu_vdec_param, + &g_svp_npu_vdec_thread, &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end1, SAMPLE_SVP_ERR_LEVEL_DEBUG, + "init media failed!\n"); + + /* set cfg */ + sample_svp_npu_acl_set_task_info(model_idx); + + ret = sample_svp_npu_acl_init_task(1, TD_FALSE, 0); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end2, SAMPLE_SVP_ERR_LEVEL_ERROR, "init task failed!\n"); + } + /* process */ + if (g_svp_npu_terminate_signal == TD_FALSE) { + ret = sample_common_svp_npu_set_threshold(&g_svp_npu_yolo_threshold[0], SAMPLE_SVP_NPU_YOLO_THRESHOLD_NUM, + &g_svp_npu_task[0]); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end3, SAMPLE_SVP_ERR_LEVEL_ERROR, + "set threshold failed!\n"); + + g_svp_npu_thread_stop = TD_FALSE; + ret = pthread_create(&g_svp_npu_thread, 0, sample_svp_npu_acl_vdec_to_vo, (td_void*)&args); + + sample_svp_check_exps_goto(ret != 0, process_end3, SAMPLE_SVP_ERR_LEVEL_ERROR, "create thread failed!\n"); + + (td_void)sample_svp_npu_acl_pause(); + + g_svp_npu_thread_stop = TD_TRUE; + pthread_join(g_svp_npu_thread, TD_NULL); + } + +process_end3: + (td_void)sample_svp_npu_acl_deinit_task(1, 0); +process_end2: + (td_void)sample_common_svp_destroy_vb_stop_vdec_vpss_vo(&g_svp_npu_vdec_param, &g_svp_npu_vdec_thread, + &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); +process_end1: + (td_void)sample_common_svp_npu_unload_model(model_idx); +process_end0: + (td_void)sample_svp_npu_acl_deinit(); + (td_void)sample_svp_npu_acl_terminate(); +} + +int main(void) +{ +#ifdef CONFIG_USER_SPACE + SDK_init(); +#endif + + sample_face_detection(); + +#ifdef CONFIG_USER_SPACE + SDK_exit(); +#endif + + return 0; +} \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20221114150205685.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20221114150205685.png new file mode 100755 index 0000000000000000000000000000000000000000..4dc4215c962c57ba0e31548fb98c29c789f149d9 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20221114150205685.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250210161601541.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250210161601541.png new file mode 100755 index 0000000000000000000000000000000000000000..80845ece8131933a4cd56ae3bd6119c38e0abd26 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250210161601541.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250210170027454.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250210170027454.png new file mode 100755 index 0000000000000000000000000000000000000000..c06081fc2c963af4d1fa8af506804beedefe1b0b Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250210170027454.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250213112932380.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250213112932380.png new file mode 100755 index 0000000000000000000000000000000000000000..8b591b3437544859f4ec76b9ca03867cc401078c Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250213112932380.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919144926220.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919144926220.png new file mode 100755 index 0000000000000000000000000000000000000000..ce52c2e8b435b703f1dcec3eccaa917d4dcd189a Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919144926220.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145314492.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145314492.png new file mode 100755 index 0000000000000000000000000000000000000000..b6380f00ccd5350fffdf2c135185c3d3b4774648 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145314492.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145335685.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145335685.png new file mode 100755 index 0000000000000000000000000000000000000000..3ff54534be7a6d7c18317982e37b206d5eff09d6 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145335685.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145846452.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145846452.png new file mode 100755 index 0000000000000000000000000000000000000000..951425ca5364e2d246378265ecb864da4df46725 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919145846452.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150059493.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150059493.png new file mode 100755 index 0000000000000000000000000000000000000000..3dd1d411dbd27dd4ae2b212af6e20fbb5ca9bada Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150059493.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150131086.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150131086.png new file mode 100755 index 0000000000000000000000000000000000000000..a2b0ce4802b9c9531b59f8a0599e607594aae646 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150131086.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150233049.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150233049.png new file mode 100755 index 0000000000000000000000000000000000000000..e6ee8810f1894fefb4db96404f952bf8f9bc85a6 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150233049.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150630870.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150630870.png new file mode 100755 index 0000000000000000000000000000000000000000..2d661646429af7ee314241ca3f86556060d7911e Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150630870.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150812107.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150812107.png new file mode 100755 index 0000000000000000000000000000000000000000..eaa958ef14096749ee02592c5790736a131c2141 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919150812107.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151018659.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151018659.png new file mode 100755 index 0000000000000000000000000000000000000000..9b09507893b65d2142be49e6461daa31a81855c4 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151018659.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151519310.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151519310.png new file mode 100755 index 0000000000000000000000000000000000000000..7f6d881a5d0e6d3f72b7a43d089b5c5a75d7f048 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151519310.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151605632.png b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151605632.png new file mode 100755 index 0000000000000000000000000000000000000000..c6aa9aad5685495d6bad5ba5d4e0c09e31ed3c7a Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/face_detection/pic/image-20250919151605632.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/Makefile b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..655332a1e534facf1e535f30523f129824e25f72 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/Makefile @@ -0,0 +1,59 @@ +# 编译所需的公共文件 +include ../mk.param + +# 编译后生成的可执行文件名 +TARGET := main + +# 编译此工程需要包含的头文件 +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR)/ +CFLAGS += -I$(SDK_SAMPLE_COMMON_DIR)/ +CFLAGS += -I$(AUDIO_SAMPLE)/adp/ +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR)/svp_npu +CFLAGS += -I$(FRUIT_IDENTIFY_SAMPLE_DIR)/ +CFLAGS += -I$(FRUIT_IDENTIFY_SAMPLE_DIR)/common/ +CFLAGS += -I$(THIRD_PARTY_DIR)/xvp_osd/include/ + +# 编译此工程需要依赖的.c或.cpp文件 +SMP_SRCS := $(AUDIO_SAMPLE)/adp/audio_aac_adp.c +SMP_SRCS += $(AUDIO_SAMPLE)/adp/audio_dl_adp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_sys.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_audio.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_ipc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_isp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vi.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vo.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_mipi_tx.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vpss.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/loadbmp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vdec.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_venc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_init.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_exit.c +SMP_SRCS += $(FRUIT_IDENTIFY_SAMPLE_DIR)/fruit_identify.c +SMP_SRCS += $(FRUIT_IDENTIFY_SAMPLE_DIR)/sample_audio.c +SMP_SRCS += $(FRUIT_IDENTIFY_SAMPLE_DIR)/common/sample_common_svp_npu_model.c +SMP_SRCS += $(FRUIT_IDENTIFY_SAMPLE_DIR)/common/sample_common_svp_npu.c +SMP_SRCS += $(FRUIT_IDENTIFY_SAMPLE_DIR)/common/sample_common_svp_osd.c +SMP_SRCS += $(FRUIT_IDENTIFY_SAMPLE_DIR)/common/sample_common_svp.c + +# 编译此工程需要包含的库和宏 +CFLAGS += -O3 -g -Wall -DUSE_USB_CAMERA +CFLAGS += -fstack-protector-strong +MPI_LIBS += $(THIRD_PARTY_DIR)/xvp_osd/lib/libxvp_osd.a + +# 根据实际的类型设置,可以用set_sensor脚本设置 +SENSOR0_TYPE = -DSENSOR0_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR1_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR2_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR3_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT + +CFLAGS += $(SENSOR0_TYPE) +CFLAGS += $(SENSOR1_TYPE) +CFLAGS += $(SENSOR2_TYPE) +CFLAGS += $(SENSOR3_TYPE) + +# 编译工程所需的mk文件 + +include ../sdk_linux.mk + + diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/README.md b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/README.md new file mode 100755 index 0000000000000000000000000000000000000000..8919851eb8da9eff1f4aaefb95c1070bdc55a0f0 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/README.md @@ -0,0 +1,131 @@ +## 2.3、fruit_identify操作指导 + +### 2.3.1、fruit_identify程序简介 + +* fruit_identify sample基于SS928V100平台开发,以EulerPi套件为例,fruit_identify sample是通过USB Camera,将采集到的图片送到水果检测模型中进行推理,当检测到特定水果时,会通过外接显示屏实时显示水果的种类以及执行度,并框住水果的具体位置,并通过耳机播放出此时识别到的水果类别。 +* fruit_identify案例主要是使用pytorch框架,基于YoloV8网络,使用自行标注的水果数据集训练出来的水果分类模型。 + +### 2.3.2、目录 + +```shell +pegasus/vendor/cust/demo/fruit_identify +|── common # 基于海思mpp/sample中的svp/common/目录下修改的代码,新增了OSD部分的内容 +|── data # 模型文件和汉字库 +|── fruit_audio # 不同水果的音频文件 +|── Makefile # 编译脚本 +|── fruit_identify.c # fruit_identif sample业务代码 +|── sample_audio.c # 音频播放的业务代码 +└── sample_audio.h # 音频播放的头文件 +``` + +![image-20250919173612332](pic/image-20250919173612332.png) + +### 2.3.3、编译 + +* **注意:在编译cust的demo之前,请确保你已经按照[patch介绍中的步骤](../../README.md#4patch介绍)把补丁打入海思SDK的sample目录下了**。 + +* 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 + +* 步骤2:使用Makefile的方式进行单编 + +* 在Ubuntu的命令行终端,分步执行下面的命令,单编 fruit_identify sample + + ``` + cd pegasus/vendor/cust/demo/fruit_identify + + make clean && make + ``` + + ![image-20250919173833285](pic/image-20250919173833285.png) + + * 在fruit_identify目录下,生成一个名为fruit_identify的 可执行文件,如下图所示: + + ![image-20250919173911326](pic/image-20250919173911326.png) + +### 2.3.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +* 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +image-20221114150205685 + +* 步骤1:将编译后生成的可执行文件、data目录(里面有模型和字库),音频文件都拷贝到SD卡中。 + +![image-20250919174107506](pic/image-20250919174107506.png) + +* 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +image-20250210161601541 + +* 在开发板的终端,执行下面的命令进行SD卡的挂载 + * 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +* 挂载成功后,如下图所示: + +![image-20250919174301632](pic/image-20250919174301632.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +* 首先需要自己准备一根网线 +* 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +* 步骤2:将编译后生成的可执行文件、data目录(里面有模型和字库),音频文件都拷贝到Windows的nfs共享路径下 + +![image-20250919175651286](pic/image-20250919175651286.png) + +* 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + * 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + + +``` +ifconfig eth0 192.168.100.100 +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20250919175810259](pic/image-20250919175810259.png) + +### 2.3.5、硬件连接 + +* 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image-20250213112932380](pic/image-20250213112932380.png) + +* 将USB 摄像头接在EulerPi开发板的USB接口上。 + +image-20250919150630870 + +### 2.3.6、功能验证 + +* 在开发板的终端执行下面的命令,运行可执行文件 + +``` +cd /mnt + +chmod +x fruit_identify + +./fruit_identify +``` + +![image-20250919175946122](pic/image-20250919175946122.png) + +* 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +image-20250210170027454 + +* 如果您看到的现象和下图现象不一致,可以确认一下USB涉嫌头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659.png) + +* 正常情况下,我们会在外接显示屏上看到有水果的区域被框出来。且在框框的左上角显示水果的种类和置信度,并且你可以在开发板上面接上耳机,可以听到检测到的水果的具体语音播报。 + +![image-20250919180706355](pic/image-20250919180706355.png) + +* 敲两下回车即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310.png) \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp.c b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp.c new file mode 100755 index 0000000000000000000000000000000000000000..79778ec97254e1250f4ea6820348267955f8df4d --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp.c @@ -0,0 +1,1036 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sample_common_svp.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ot_common.h" +#include "ot_common_video.h" +#include "ot_common_sys.h" +#include "ot_common_svp.h" +#include "ss_mpi_vb.h" +#include "sample_comm.h" + +#define OT_VPSS_CHN_NUM 2 +#define OT_SAMPLE_IVE_MAX_POOL_CNT 128 +#define OT_SAMPLE_IVE_DRAW_THICK 2 + +#define SAMPLE_SVP_BLK_CNT 16 +#define SMAPLE_SVP_DISPLAY_BUF_LEN 3 +#define SAMPLE_SVP_VI_CHN_INTERVAL 4 +#define SAMPLE_SVP_VDEC_CHN_0 0 +#define SAMPLE_SVP_VDEC_CHN_NUM 1 +#define SAMPLE_SVP_VPSS_BORDER_WIDTH 2 +#define SAMPLE_SVP_VO_DIS_BUF_LEN 3 +#define SAMPLE_SVP_MAX_WIDTH 32768 +#define SAMPLE_SVP_NUM_TWO 2 +#define SAMPLE_SVP_DSP_BIN_NUM_PER 4 +#define SAMPLE_SVP_DSP_MEM_TYPE_SYS_DDR 0 +#define SAMPLE_SVP_DSP_MEM_TYPE_IRAM 1 +#define SAMPLE_SVP_DSP_MEM_TYPE_DRAM_0 2 +#define SAMPLE_SVP_DSP_MEM_TYPE_DRAM_1 3 + +static td_bool g_sample_svp_init_flag = TD_FALSE; + +static td_s32 sample_common_svp_get_pic_type_by_sns_type(sample_sns_type sns_type, ot_pic_size size[], td_u32 num) +{ + sample_svp_check_exps_return(num > OT_VPSS_CHN_NUM, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "num(%u) can't be larger than (%u)\n", num, OT_VPSS_CHN_NUM); + switch (sns_type) { + case HY_S0603_MIPI_8M_30FPS_12BIT: + case HY_S0603_MIPI_8M_30FPS_10BIT_WDR2TO1: + size[0] = PIC_3840X2160; + break; + default: + size[0] = PIC_3840X2160; + break; + } + return TD_SUCCESS; +} + +static td_s32 sample_comm_svp_get_pic_size(ot_pic_size pic_type, td_u64 *size) +{ + td_s32 ret; + ot_pic_buf_attr pic_buf_attr = {0}; + ot_size pic_size = {0}; + + ret = sample_comm_sys_get_pic_size(pic_type, &pic_size); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_comm_sys_get_pic_size failed,Error(%#x)!\n", ret); + pic_buf_attr.width = pic_size.width; + pic_buf_attr.height = pic_size.height; + pic_buf_attr.compress_mode = OT_COMPRESS_MODE_NONE; + pic_buf_attr.align = OT_DEFAULT_ALIGN; + pic_buf_attr.bit_width = OT_DATA_BIT_WIDTH_8; + pic_buf_attr.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_422; + *size = ot_common_get_pic_buf_size(&pic_buf_attr); + return TD_SUCCESS; +} + +/* System init */ +static td_s32 sample_comm_svp_sys_init(td_bool vi_en) +{ + td_s32 ret; + ot_vb_cfg vb_cfg; + ot_pic_size pic_type; + td_u64 size = 0; + sample_sns_type sns_type = SENSOR0_TYPE; + + ret = ss_mpi_sys_exit(); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_sys_exit failed!\n", ret); + ret = ss_mpi_vb_exit(); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_vb_exit failed!\n", ret); + + (td_void)memset_s(&vb_cfg, sizeof(ot_vb_cfg), 0, sizeof(ot_vb_cfg)); + + if (vi_en == TD_FALSE) { + vb_cfg.max_pool_cnt = SAMPLE_SVP_VB_POOL_NUM; + vb_cfg.common_pool[1].blk_size = SAMPLE_SVP_D1_PAL_WIDTH * SAMPLE_SVP_D1_PAL_HEIGHT * SAMPLE_SVP_VB_POOL_NUM; + vb_cfg.common_pool[1].blk_cnt = 1; + } else { + ret = sample_common_svp_get_pic_type_by_sns_type(sns_type, &pic_type, OT_SVP_MAX_VPSS_CHN_NUM); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_common_svp_get_pic_type_by_sns_type failed!\n"); + ret = sample_comm_svp_get_pic_size(pic_type, &size); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):sample_common_svp_npu_get_pic_size failed!\n", ret); + vb_cfg.max_pool_cnt = SAMPLE_SVP_VB_POOL_NUM; + vb_cfg.common_pool[1].blk_size = size; + vb_cfg.common_pool[1].blk_cnt = SAMPLE_SVP_BLK_CNT; + } + + ret = ss_mpi_vb_set_cfg((const ot_vb_cfg *)&vb_cfg); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_vb_set_config failed!\n", ret); + + ret = ss_mpi_vb_init(); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_vb_init failed!\n", ret); + + ret = ss_mpi_sys_init(); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_sys_init failed!\n", ret); + + return ret; +} + +/* System exit */ +static td_s32 sample_comm_svp_sys_exit(td_void) +{ + td_s32 ret; + + ret = ss_mpi_sys_exit(); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_sys_exit failed!\n", ret); + + ret = ss_mpi_vb_exit(); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_vb_exit failed!\n", ret); + + return TD_SUCCESS; +} + +/* System init */ +td_s32 sample_common_svp_check_sys_init(td_bool vi_en) +{ + if (g_sample_svp_init_flag == TD_FALSE) { + if (sample_comm_svp_sys_init(vi_en) != TD_SUCCESS) { + sample_svp_trace_err("Svp mpi init failed!\n"); + return TD_FALSE; + } + g_sample_svp_init_flag = TD_TRUE; + } + + sample_svp_trace_info("Svp mpi init ok!\n"); + return TD_TRUE; +} + +/* System exit */ +td_void sample_common_svp_check_sys_exit(td_void) +{ + td_s32 ret; + + if (g_sample_svp_init_flag == TD_TRUE) { + ret = sample_comm_svp_sys_exit(); + if (ret != TD_SUCCESS) { + sample_svp_trace_err("svp mpi exit failed!\n"); + } + } + g_sample_svp_init_flag = TD_FALSE; + sample_svp_trace_info("Svp mpi exit ok!\n"); +} + +/* Align */ +td_u32 sample_common_svp_align(td_u32 size, td_u16 align) +{ + td_u32 stride; + + sample_svp_check_exps_return(align == 0, 0, SAMPLE_SVP_ERR_LEVEL_ERROR, "align can't be zero!\n"); + sample_svp_check_exps_return((size < 1) || (size > SAMPLE_SVP_MAX_WIDTH), 0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "size(%u) must be [1, %u]\n", size, SAMPLE_SVP_MAX_WIDTH); + stride = size + (align - size % align) % align; + return stride; +} + +/* Create mem info */ +td_s32 sample_common_svp_create_mem_info(ot_svp_mem_info *mem_info, td_u32 size, td_u32 addr_offset) +{ + td_s32 ret = TD_FAILURE; + td_u32 size_tmp; + + sample_svp_check_exps_return(mem_info == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "mem_info can't be zero\n"); + + size_tmp = size + addr_offset; + mem_info->size = size; + ret = ss_mpi_sys_mmz_alloc((td_phys_addr_t *)(&mem_info->phys_addr), + (void **)&mem_info->virt_addr, TD_NULL, TD_NULL, size_tmp); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):ss_mpi_sys_alloc failed!\n", ret); + + mem_info->phys_addr += addr_offset; + mem_info->virt_addr += addr_offset; + + return ret; +} + +/* Destory mem info */ +td_void sample_common_svp_destroy_mem_info(ot_svp_mem_info *mem_info, td_u32 addr_offset) +{ + sample_svp_check_exps_return_void(mem_info == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "mem_info can't be zero\n"); + + if ((mem_info->virt_addr != 0) && (mem_info->phys_addr != 0)) { + (td_void)ss_mpi_sys_mmz_free(mem_info->phys_addr - addr_offset, + sample_svp_convert_addr_to_ptr(void, (mem_info->virt_addr - addr_offset))); + } + (td_void)memset_s(mem_info, sizeof(*mem_info), 0, sizeof(*mem_info)); +} +/* Malloc memory */ +td_s32 sample_common_svp_malloc_mem(td_char *mmb, td_char *zone, td_phys_addr_t *phys_addr, + td_void **virt_addr, td_u32 size) +{ + td_s32 ret = TD_FAILURE; + + sample_svp_check_exps_return(phys_addr == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "phys_addr can't be null\n"); + sample_svp_check_exps_return(virt_addr == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "virt_addr can't be null\n"); + ret = ss_mpi_sys_mmz_alloc((td_phys_addr_t *)phys_addr, virt_addr, mmb, zone, size); + + return ret; +} + +/* Malloc memory with cached */ +td_s32 sample_common_svp_malloc_cached(td_char *mmb, td_char *zone, td_phys_addr_t *phys_addr, + td_void **virt_addr, td_u32 size) +{ + td_s32 ret = TD_FAILURE; + + sample_svp_check_exps_return(phys_addr == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "phys_addr can't be null\n"); + sample_svp_check_exps_return(virt_addr == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "virt_addr can't be null\n"); + ret = ss_mpi_sys_mmz_alloc_cached((td_phys_addr_t *)phys_addr, virt_addr, mmb, zone, size); + + return ret; +} + +/* Fulsh cached */ +td_s32 sample_common_svp_flush_cache(td_phys_addr_t phys_addr, td_void *virt_addr, td_u32 size) +{ + td_s32 ret = TD_FAILURE; + + sample_svp_check_exps_return(virt_addr == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "virt_addr can't be null\n"); + ret = ss_mpi_sys_flush_cache((td_phys_addr_t)phys_addr, virt_addr, size); + return ret; +} + +/* + * function : Init Vb + */ +static td_s32 sample_common_svp_vb_init(ot_pic_size *pic_type, ot_size *pic_size, + td_u32 vpss_chn_num) +{ + td_s32 ret; + td_u32 i; + ot_vb_cfg vb_cfg = {0}; + ot_pic_buf_attr pic_buf_attr; + ot_vb_calc_cfg calc_cfg; + ot_vi_vpss_mode_type mode_type = OT_VI_ONLINE_VPSS_OFFLINE; + ot_vi_video_mode video_mode = OT_VI_VIDEO_MODE_NORM; + + vb_cfg.max_pool_cnt = OT_SAMPLE_IVE_MAX_POOL_CNT; + + ret = sample_comm_sys_get_pic_size(pic_type[0], &pic_size[0]); + sample_svp_check_exps_goto(ret != TD_SUCCESS, vb_fail_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_comm_sys_get_pic_size failed,Error(%#x)!\n", ret); + pic_buf_attr.width = pic_size[0].width; + pic_buf_attr.height = pic_size[0].height; + pic_buf_attr.align = OT_DEFAULT_ALIGN; + pic_buf_attr.bit_width = OT_DATA_BIT_WIDTH_8; + pic_buf_attr.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_422; + pic_buf_attr.compress_mode = OT_COMPRESS_MODE_NONE; + + ot_common_get_pic_buf_cfg(&pic_buf_attr, &calc_cfg); + + vb_cfg.common_pool[0].blk_size = calc_cfg.vb_size; + vb_cfg.common_pool[0].blk_cnt = SAMPLE_SVP_BLK_CNT; + + for (i = 1; (i < vpss_chn_num) && (i < OT_VB_MAX_COMMON_POOLS); i++) { + ret = sample_comm_sys_get_pic_size(pic_type[i], &pic_size[i]); + sample_svp_check_exps_goto(ret != TD_SUCCESS, vb_fail_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_comm_sys_get_pic_size failed,Error(%#x)!\n", ret); + pic_buf_attr.width = pic_size[i].width; + pic_buf_attr.height = pic_size[i].height; + pic_buf_attr.compress_mode = OT_COMPRESS_MODE_NONE; + pic_buf_attr.align = OT_DEFAULT_ALIGN; + + ot_common_get_pic_buf_cfg(&pic_buf_attr, &calc_cfg); + + /* comm video buffer */ + vb_cfg.common_pool[i].blk_size = calc_cfg.vb_size; + vb_cfg.common_pool[i].blk_cnt = SAMPLE_SVP_BLK_CNT; + } + + ret = sample_comm_sys_init_with_vb_supplement(&vb_cfg, OT_VB_SUPPLEMENT_BNR_MOT_MASK); + sample_svp_check_exps_goto(ret != TD_SUCCESS, vb_fail_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_comm_sys_init failed,Error(%#x)!\n", ret); + + ret = sample_comm_vi_set_vi_vpss_mode(mode_type, video_mode); + sample_svp_check_exps_goto(ret != TD_SUCCESS, vb_fail_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_comm_vi_set_vi_vpss_mode failed!\n"); + return ret; +vb_fail_1: + sample_comm_sys_exit(); +vb_fail_0: + return ret; +} + +td_s32 sample_common_svp_vgs_fill_rect(const ot_video_frame_info *frame_info, + ot_sample_svp_rect_info *rect, td_u32 color) +{ + ot_vgs_handle vgs_handle = -1; + td_s32 ret = TD_FAILURE; + td_u16 i; + ot_vgs_task_attr vgs_task; + ot_cover vgs_add_cover; + + sample_svp_check_exps_return(frame_info == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "frame_info can't be null\n"); + sample_svp_check_exps_return(rect == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "rect can't be null\n"); + sample_svp_check_exps_return(rect->num > OT_SVP_RECT_NUM, ret, + SAMPLE_SVP_ERR_LEVEL_ERROR, "rect->num can't lager than %u\n", OT_SVP_RECT_NUM); + if (rect->num == 0) { + return TD_SUCCESS; + } + + ret = ss_mpi_vgs_begin_job(&vgs_handle); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Vgs begin job fail,Error(%#x)\n", ret); + + ret = memcpy_s(&vgs_task.img_in, sizeof(ot_video_frame_info), frame_info, sizeof(ot_video_frame_info)); + sample_svp_check_exps_goto(ret != EOK, fail, SAMPLE_SVP_ERR_LEVEL_ERROR, "get img_in failed\n"); + ret = memcpy_s(&vgs_task.img_out, sizeof(ot_video_frame_info), frame_info, sizeof(ot_video_frame_info)); + sample_svp_check_exps_goto(ret != EOK, fail, SAMPLE_SVP_ERR_LEVEL_ERROR, "get img_out failed\n"); + + vgs_add_cover.type = OT_COVER_QUAD; + vgs_add_cover.color = color; + for (i = 0; i < rect->num; i++) { + vgs_add_cover.quad.is_solid = TD_FALSE; + vgs_add_cover.quad.thick = OT_SAMPLE_IVE_DRAW_THICK; + ret = memcpy_s(vgs_add_cover.quad.point, sizeof(rect->rect[i].point), + rect->rect[i].point, sizeof(rect->rect[i].point)); + sample_svp_check_exps_goto(ret != EOK, fail, SAMPLE_SVP_ERR_LEVEL_ERROR, "get point failed\n"); + ret = ss_mpi_vgs_add_cover_task(vgs_handle, &vgs_task, &vgs_add_cover, 1); + sample_svp_check_exps_goto(ret != TD_SUCCESS, fail, SAMPLE_SVP_ERR_LEVEL_ERROR, + "ss_mpi_vgs_add_cover_task fail,Error(%#x)\n", ret); + } + ret = ss_mpi_vgs_end_job(vgs_handle); + sample_svp_check_exps_goto(ret != TD_SUCCESS, fail, SAMPLE_SVP_ERR_LEVEL_ERROR, + "ss_mpi_vgs_end_job fail,Error(%#x)\n", ret); + return ret; +fail: + ss_mpi_vgs_cancel_job(vgs_handle); + return ret; +} + +/* function : Start Vpss */ +static td_s32 sample_common_svp_start_vpss(td_s32 vpss_grp_cnt, ot_size *pic_size, td_u32 vpss_chn_num) +{ + td_u32 i; + ot_vpss_chn_attr vpss_chn_attr[OT_VPSS_MAX_CHN_NUM]; + ot_vpss_grp_attr vpss_grp_attr; + td_bool chn_enable[OT_VPSS_MAX_CHN_NUM] = { TD_TRUE, TD_TRUE, TD_FALSE, TD_FALSE }; + ot_vpss_grp vpss_grp; + td_s32 ret; + + (td_void)memset_s(&vpss_grp_attr, sizeof(ot_vpss_grp_attr), 0, sizeof(ot_vpss_grp_attr)); + sample_comm_vpss_get_default_grp_attr(&vpss_grp_attr); + vpss_grp_attr.max_width = pic_size[0].width; + vpss_grp_attr.max_height = pic_size[0].height; + vpss_grp_attr.nr_attr.compress_mode = OT_COMPRESS_MODE_NONE; + /* VPSS only onle channel0 support compress seg mode */ + sample_comm_vpss_get_default_chn_attr(&vpss_chn_attr[0]); + vpss_chn_attr[0].width = pic_size[0].width; + vpss_chn_attr[0].height = pic_size[0].height; + vpss_chn_attr[0].compress_mode = OT_COMPRESS_MODE_NONE; + vpss_chn_attr[0].depth = 1; + + for (i = 1; i < vpss_chn_num; i++) { + (td_void)memset_s(&vpss_chn_attr[i], sizeof(ot_vpss_chn_attr), 0, sizeof(ot_vpss_chn_attr)); + sample_comm_vpss_get_default_chn_attr(&vpss_chn_attr[i]); + vpss_chn_attr[i].width = pic_size[i].width; + vpss_chn_attr[i].height = pic_size[i].height; + vpss_chn_attr[i].compress_mode = OT_COMPRESS_MODE_NONE; + vpss_chn_attr[i].depth = 1; + } + + for (vpss_grp = 0; vpss_grp < vpss_grp_cnt; vpss_grp++) { + ret = sample_common_vpss_start(vpss_grp, chn_enable, &vpss_grp_attr, vpss_chn_attr, OT_VPSS_MAX_CHN_NUM); + if (ret != TD_SUCCESS) { + sample_svp_trace_err("failed with %#x!\n", ret); + return TD_FAILURE; + } + } + return TD_SUCCESS; +} + +/* function : Stop Vpss */ +static td_void sample_common_svp_stop_vpss(td_s32 vpss_grp_cnt, td_u32 vpss_chn_num) +{ + ot_vpss_grp vpss_grp = 0; + td_bool chn_enable[OT_VPSS_MAX_CHN_NUM] = { TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE }; + td_s32 i; + for (i = 0; (i < vpss_chn_num) && (i < OT_VPSS_MAX_CHN_NUM); i++) { + chn_enable[i] = TD_TRUE; + } + for (i = 0; (i < vpss_grp_cnt) && (i < OT_VPSS_MAX_CHN_NUM); i++) { + sample_common_vpss_stop(vpss_grp, chn_enable, OT_VPSS_MAX_CHN_NUM); + vpss_grp++; + } +} + +static td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg) +{ + ot_rect def_disp_rect = {0, 0, 1920, 1080}; + ot_size def_img_size = {1920, 1080}; + + if (vo_cfg == TD_NULL) { + sample_svp_trace_err("error:argument can not be TD_NULL\n"); + return TD_FAILURE; + } + + vo_cfg->vo_dev = SAMPLE_VO_DEV_UHD; + + vo_cfg->vo_intf_type = OT_VO_INTF_HDMI; + vo_cfg->intf_sync = OT_VO_OUT_1080P60; + vo_cfg->bg_color = COLOR_RGB_BLACK; + vo_cfg->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vo_cfg->disp_rect = def_disp_rect; + vo_cfg->image_size = def_img_size; + vo_cfg->vo_part_mode = OT_VO_PARTITION_MODE_SINGLE; + vo_cfg->dis_buf_len = 3; /* 3: def buf len for single */ + vo_cfg->dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8; + vo_cfg->vo_mode = VO_MODE_1MUX; + vo_cfg->compress_mode = OT_COMPRESS_MODE_NONE; + + return TD_SUCCESS; +} + +/* + * function : Start Vo + */ +static td_s32 sample_common_svp_start_vo(const ot_sample_svp_switch *vo_venc_switch, sample_vo_cfg *vo_cfg) +{ + td_s32 ret; + sample_svp_check_exps_return(vo_venc_switch == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "vo_venc_switch can't be null\n"); + sample_svp_check_exps_return(vo_cfg == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "vo_cfg can't be null\n"); + + if (vo_venc_switch->is_vo_open == TD_FALSE) { + return TD_SUCCESS; + } + ret = sample_common_svp_get_def_vo_cfg(vo_cfg); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_get_def_vo_cfg failed!\n", ret); + ret = sample_comm_vo_start_vo(vo_cfg); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_vo_start_vo failed!\n", ret); + return ret; +} + +/* + * function : Stop Vo + */ +static td_void sample_common_svp_stop_vo(const ot_sample_svp_switch *vo_venc_switch, sample_vo_cfg *vo_cfg) +{ + sample_svp_check_exps_return_void(vo_venc_switch == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "vo_venc_switch can't be null\n"); + sample_svp_check_exps_return_void(vo_cfg == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "vo_cfg can't be null\n"); + + if (vo_venc_switch->is_vo_open == TD_FALSE) { + return; + } + (td_void)sample_comm_vo_stop_vo(vo_cfg); +} + +static td_s32 sample_common_svp_vi_bind_multi_vpss(td_s32 vpss_grp_cnt, td_s32 vi_chn_cnt, + td_s32 vi_chn_interval) +{ + td_s32 ret; + td_s32 loop; + ot_vi_chn vi_chn; + ot_vpss_grp vpss_grp = 0; + + for (loop = 0; loop < vi_chn_cnt && vpss_grp < vpss_grp_cnt; loop++) { + vi_chn = loop * vi_chn_interval; + ret = sample_comm_vi_bind_vpss(0, vi_chn, vpss_grp, 0); + if (ret != TD_SUCCESS) { + sample_svp_trace_err("vi bind vpss failed!\n"); + return ret; + } + vpss_grp++; + } + + return TD_SUCCESS; +} + +static td_s32 sample_common_svp_vi_unbind_multi_vpss(td_s32 vpss_grp_cnt, td_s32 vi_chn_cnt, + td_s32 vi_chn_interval) +{ + td_s32 ret; + td_s32 loop; + ot_vi_chn vi_chn; + ot_vpss_grp vpss_grp = 0; + + for (loop = 0; loop < vi_chn_cnt && vpss_grp < vpss_grp_cnt; loop++) { + vi_chn = loop * vi_chn_interval; + ret = sample_comm_vi_un_bind_vpss(0, vi_chn, vpss_grp, 0); + if (ret != TD_SUCCESS) { + sample_svp_trace_err("vi bind vpss failed!\n"); + return ret; + } + + vpss_grp++; + } + + return TD_SUCCESS; +} + +static td_s32 sample_common_svp_set_vi_cfg(sample_vi_cfg *vi_cfg, ot_pic_size *pic_type, + td_u32 pic_type_len, ot_pic_size *ext_pic_size_type, sample_sns_type sns_type) +{ + sample_comm_vi_get_default_vi_cfg(sns_type, vi_cfg); + sample_svp_check_exps_return(pic_type_len < OT_VPSS_CHN_NUM, + TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "pic_type_len is illegal!\n"); + pic_type[1] = *ext_pic_size_type; + + return TD_SUCCESS; +} + +static td_s32 sample_common_svp_start_venc(const ot_sample_svp_switch *switch_ptr, + sample_vo_cfg *vo_cfg, ot_pic_size *pic_type, td_u32 chn_num) +{ + td_s32 ret = TD_SUCCESS; + ot_venc_chn h264_chn = 0; + sample_comm_venc_chn_param chn_param; + ot_size ven_size = {1920, 1080}; + + sample_svp_check_exps_goto(chn_num == 0, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, "Error(%#x),chn_num(%u) can't be 0!\n", + ret, chn_num); + if (switch_ptr->is_venc_open == TD_TRUE) { + ret = sample_comm_venc_get_gop_attr(OT_VENC_GOP_MODE_NORMAL_P, &chn_param.gop_attr); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_venc_get_gop_attr failed!\n", ret); + chn_param.frame_rate = 30; /* 30 is a number */ + chn_param.stats_time = 1; /* 1 is a number */ + chn_param.gop = 30; /* 30 is a number */ + chn_param.venc_size = ven_size; + chn_param.size = pic_type[0]; + chn_param.profile = 0; + chn_param.is_rcn_ref_share_buf = TD_TRUE; + + chn_param.type = OT_PT_H264; + chn_param.rc_mode = SAMPLE_RC_CBR; + + ret = sample_comm_venc_start(h264_chn, &chn_param); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_venc_start failed!\n", ret); + + ret = sample_comm_venc_start_get_stream(&h264_chn, 1); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_venc_start_get_stream failed!\n", ret); + } + return ret; + +end_1: + if (switch_ptr->is_venc_open == TD_TRUE) { + sample_comm_venc_stop(h264_chn); + } +end_0: + sample_common_svp_stop_vo(switch_ptr, vo_cfg); + return ret; +} + +/* + * function : Start Vi/Vpss/Venc/Vo + */ +td_s32 sample_common_svp_start_vi_vpss_venc_vo(sample_vi_cfg *vi_cfg, + ot_sample_svp_switch *switch_ptr, ot_pic_size *ext_pic_size_type) +{ + ot_size pic_size[OT_VPSS_CHN_NUM]; + ot_pic_size pic_type[OT_VPSS_CHN_NUM]; + sample_vo_cfg vo_cfg; + ot_pic_size venc_pic_type[SAMPLE_SVP_VDEC_CHN_NUM] = {PIC_1080P}; + + const td_s32 vpss_grp_cnt = 1; + td_s32 ret = TD_FAILURE; + sample_sns_type sns_type = SENSOR0_TYPE; + + sample_svp_check_exps_return(vi_cfg == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "vi_cfg can't be null\n"); + sample_svp_check_exps_return(switch_ptr == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "switch_ptr can't be null\n"); + sample_svp_check_exps_return(ext_pic_size_type == TD_NULL, ret, + SAMPLE_SVP_ERR_LEVEL_ERROR, "ext_pic_size_type can't be null\n"); + + ret = sample_common_svp_get_pic_type_by_sns_type(sns_type, pic_type, OT_VPSS_CHN_NUM); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_common_svp_get_pic_type_by_sns_type failed!\n"); + ret = sample_common_svp_set_vi_cfg(vi_cfg, pic_type, OT_VPSS_CHN_NUM, ext_pic_size_type, sns_type); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_common_svp_set_vi_cfg failed,Error:%#x\n", ret); + + /* step 1: Init vb */ + ret = sample_common_svp_vb_init(pic_type, pic_size, OT_VPSS_CHN_NUM); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_vb_init failed!\n", ret); + + /* step 2: Start vi */ + ret = sample_comm_vi_start_vi(vi_cfg); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_vi_start_vi failed!\n", ret); + + /* step 3: Bind vpss to vi */ + ret = sample_common_svp_vi_bind_multi_vpss(vpss_grp_cnt, 1, 1); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_2, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_vi_bind_multi_vpss failed!\n", ret); + + /* step 4: Start vpss */ + ret = sample_common_svp_start_vpss(vpss_grp_cnt, pic_size, OT_VPSS_CHN_NUM); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_3, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vpss failed!\n", ret); + + /* step 5: Set vi frame, Start Vo */ + ret = sample_common_svp_start_vo(switch_ptr, &vo_cfg); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_4, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_set_vi_frame failed!\n", ret); + + /* step 6: Start Venc */ + ret = sample_common_svp_start_venc(switch_ptr, &vo_cfg, venc_pic_type, SAMPLE_SVP_VDEC_CHN_NUM); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_4, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vencb failed!\n", ret); + + return TD_SUCCESS; +end_init_4: + sample_common_svp_stop_vpss(vpss_grp_cnt, OT_VPSS_CHN_NUM); +end_init_3: + ret = sample_common_svp_vi_unbind_multi_vpss(vpss_grp_cnt, 1, 1); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, "svp_vi_unbind_multi_vpss failed!\n"); +end_init_2: + sample_comm_vi_stop_vi(vi_cfg); +end_init_1: /* system exit */ + sample_comm_sys_exit(); + (td_void)memset_s(vi_cfg, sizeof(sample_vi_cfg), 0, sizeof(sample_vi_cfg)); + return ret; +} +static td_void sample_common_svp_stop_venc(const ot_sample_svp_switch *vo_venc_switch) +{ + if (vo_venc_switch->is_venc_open == TD_TRUE) { + sample_comm_venc_stop_get_stream(1); + sample_comm_venc_stop(0); + } +} +/* + * function : Stop Vi/Vpss/Venc/Vo + */ +td_void sample_common_svp_stop_vi_vpss_venc_vo(sample_vi_cfg *vi_cfg, + ot_sample_svp_switch *switch_ptr) +{ + sample_vo_cfg vo_cfg = {0}; + td_s32 ret; + const td_s32 vpss_grp_cnt = 1; + + sample_svp_check_exps_return_void(vi_cfg == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "vi_cfg can't be null\n"); + sample_svp_check_exps_return_void(switch_ptr == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "switch_ptr can't be null\n"); + + sample_common_svp_stop_venc(switch_ptr); + + if (switch_ptr->is_vo_open == TD_TRUE) { + (td_void)sample_common_svp_get_def_vo_cfg(&vo_cfg); + sample_common_svp_stop_vo(switch_ptr, &vo_cfg); + } + + ret = sample_common_svp_vi_unbind_multi_vpss(vpss_grp_cnt, 1, 1); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_common_svp_vi_unbind_multi_vpss failed\n"); + sample_common_svp_stop_vpss(vpss_grp_cnt, OT_VPSS_CHN_NUM); + sample_comm_vi_stop_vi(vi_cfg); + sample_comm_sys_exit(); + + (td_void)memset_s(vi_cfg, sizeof(sample_vi_cfg), 0, sizeof(sample_vi_cfg)); +} + +static td_s32 sample_common_svp_start_vdec(td_u32 chn_num, sample_vdec_attr *vdec_attr, td_u32 arr_len) +{ + td_s32 ret; + ret = sample_comm_vdec_init_vb_pool(chn_num, vdec_attr, arr_len); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_vdec_init_vb_pool failed!\n", ret); + + ret = sample_comm_vdec_start(chn_num, vdec_attr, arr_len); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x), sample_comm_vdec_start failed!\n", ret); + + ret = ss_mpi_vdec_set_display_mode(SAMPLE_SVP_VDEC_CHN_0, OT_VIDEO_DISPLAY_MODE_PREVIEW); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x), sample_comm_vdec_start failed!\n", ret); + + return ret; +end_1: + sample_comm_vdec_exit_vb_pool(); + return ret; +} + +static td_void sample_common_svp_stop_vdec(td_u32 chn_num) +{ + td_s32 ret; + ret = sample_comm_vdec_stop(chn_num); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, "sample_comm_vdec_stop failed\n"); + sample_comm_vdec_exit_vb_pool(); +} + +static td_s32 sample_common_svp_vpss_bind_vdec(td_s32 vpss_grp_cnt, td_s32 vdec_chn) +{ + td_s32 i; + td_s32 j; + td_s32 ret; + for (i = 0; i < vpss_grp_cnt; i++) { + ret = sample_comm_vdec_bind_vpss(vdec_chn, i); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x), sample_comm_vdec_bind_vpss failed!\n", ret); + } + return ret; +end_1: + for (j = 0; j < i; j++) { + sample_comm_vdec_un_bind_vpss(vdec_chn, j); + } + return ret; +} + +static td_void sample_common_svp_vpss_unbind_vdec(td_s32 vpss_grp_cnt, td_s32 vdec_chn) +{ + td_s32 i; + for (i = 0; i < vpss_grp_cnt; i++) { + sample_comm_vdec_un_bind_vpss(vdec_chn, i); + } +} + +static td_s32 sample_common_svp_create_vb(ot_sample_svp_media_cfg *media_cfg) +{ + td_s32 ret = OT_INVALID_VALUE; + td_u32 i; + td_u32 j; + td_u64 blk_size; + ot_vb_pool_cfg vb_pool_cfg = { 0 }; + ot_pic_buf_attr pic_buf_attr = {0}; + + sample_svp_check_exps_return(media_cfg == TD_NULL, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "media_cfg is NULL!\n"); + + sample_svp_check_exps_return((media_cfg->chn_num == 0) || (media_cfg->chn_num > OT_SVP_MAX_VPSS_CHN_NUM), ret, + SAMPLE_SVP_ERR_LEVEL_ERROR, "media_cfg->chn_num must be [1, %d],Error(%#x)!\n", OT_SVP_MAX_VPSS_CHN_NUM, ret); + + for (i = 0; i < media_cfg->chn_num; i++) { + if (media_cfg->pic_type[i] != PIC_BUTT) { + ret = sample_comm_sys_get_pic_size(media_cfg->pic_type[i], &media_cfg->pic_size[i]); + sample_svp_check_exps_goto(ret != TD_SUCCESS, vb_fail_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_comm_sys_get_pic_size failed,Error(%#x)!\n", ret); + } + pic_buf_attr.width = media_cfg->pic_size[i].width; + pic_buf_attr.height = media_cfg->pic_size[i].height; + pic_buf_attr.compress_mode = OT_COMPRESS_MODE_NONE; + pic_buf_attr.align = OT_DEFAULT_ALIGN; + pic_buf_attr.bit_width = OT_DATA_BIT_WIDTH_8; + pic_buf_attr.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_422; + blk_size = ot_common_get_pic_buf_size(&pic_buf_attr); + vb_pool_cfg.blk_size = blk_size; + vb_pool_cfg.blk_cnt = SAMPLE_SVP_BLK_CNT; + media_cfg->vb_pool[i] = ss_mpi_vb_create_pool(&vb_pool_cfg); + } + return TD_SUCCESS; +vb_fail_0: + for (j = 0; j < i; j++) { + (td_void)ss_mpi_vb_destroy_pool(media_cfg->vb_pool[j]); + } + return TD_FAILURE; +} + +static td_void sample_common_svp_destroy_vb(ot_sample_svp_media_cfg *media_cfg) +{ + td_u32 i; + for (i = 0; i < media_cfg->chn_num; i++) { + (td_void)ss_mpi_vb_destroy_pool(media_cfg->vb_pool[i]); + } +} +static td_s32 sample_common_svp_vpss_attach_vb(ot_sample_svp_media_cfg *media_cfg, td_s32 vpss_grp_cnt) +{ + ot_vpss_grp grp; + ot_vpss_grp grp_tmp; + ot_vpss_chn chn; + ot_vpss_grp chn_tmp; + td_s32 ret; + + for (grp = 0; grp < vpss_grp_cnt; grp++) { + for (chn = 0; chn < media_cfg->chn_num; chn++) { + ret = ss_mpi_vpss_attach_vb_pool(grp, chn, media_cfg->vb_pool[chn]); + if (ret == TD_SUCCESS) { + continue; + } + for (chn_tmp = 0; chn_tmp < chn; chn_tmp++) { + (td_void)ss_mpi_vpss_detach_vb_pool(grp, chn_tmp); + } + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x), ss_mpi_vpss_attach_vb_pool failed!\n", ret); + } + } + return ret; +end_0: + for (grp_tmp = 0; grp_tmp < grp; grp_tmp++) { + for (chn_tmp = 0; chn_tmp < media_cfg->chn_num; chn_tmp++) { + (td_void)ss_mpi_vpss_detach_vb_pool(grp_tmp, chn_tmp); + } + } + return ret; +} + +static td_void sample_common_svp_vpss_detach_vb(ot_sample_svp_media_cfg *media_cfg, td_s32 vpss_grp_cnt) +{ + ot_vpss_grp grp; + ot_vpss_chn chn; + + for (grp = 0; grp < vpss_grp_cnt; grp++) { + for (chn = 0; chn < media_cfg->chn_num; chn++) { + (td_void)ss_mpi_vpss_detach_vb_pool(grp, chn); + } + } +} + +td_s32 sample_common_svp_create_vb_start_vdec_vpss_vo(sample_vdec_attr *vdec_attr, vdec_thread_param *vdec_send, + pthread_t *vdec_thread, ot_sample_svp_media_cfg *media_cfg, sample_vo_cfg *vo_cfg) +{ + const td_s32 vpss_grp_cnt = 1; + td_s32 ret; + /* step 1: Init vb */ + ret = sample_common_svp_create_vb(media_cfg); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_create_vb failed!\n", ret); + /* step 2: start vdec */ + ret = sample_common_svp_start_vdec(SAMPLE_SVP_VDEC_CHN_NUM, vdec_attr, SAMPLE_SVP_VDEC_CHN_NUM); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x), sample_common_svp_start_vdec failed!\n", ret); + /* step 3: Start vpss */ + ret = sample_common_svp_start_vpss(vpss_grp_cnt, media_cfg->pic_size, media_cfg->chn_num); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_2, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vpss failed!\n", ret); + + ret = sample_common_svp_vpss_attach_vb(media_cfg, vpss_grp_cnt); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_3, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vpss failed!\n", ret); + + /* step 4: Bind vpss to vdec */ + ret = sample_common_svp_vpss_bind_vdec(vpss_grp_cnt, SAMPLE_SVP_VDEC_CHN_0); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_4, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_vdec_bind_vpss failed!\n", ret); + + /* step 5: Start vo */ + ret = sample_common_svp_start_vo(&(media_cfg->svp_switch), vo_cfg); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_5, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vo failed!\n", ret); + + /* step 5: Start Send thread */ + sample_comm_vdec_start_send_stream(SAMPLE_SVP_VDEC_CHN_NUM, vdec_send, vdec_thread, SAMPLE_SVP_VDEC_CHN_NUM, + SAMPLE_SVP_VDEC_CHN_NUM); + + /* step 6: Start Venc */ + ret = sample_common_svp_start_venc(&(media_cfg->svp_switch), vo_cfg, media_cfg->pic_type, + SAMPLE_SVP_VDEC_CHN_NUM); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_6, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_venc failed!\n", ret); + + return ret; +end_init_6: + sample_comm_vdec_stop_send_stream(SAMPLE_SVP_VDEC_CHN_NUM, vdec_send, vdec_thread, SAMPLE_SVP_VDEC_CHN_NUM, + SAMPLE_SVP_VDEC_CHN_NUM); + sample_common_svp_stop_vo(&(media_cfg->svp_switch), vo_cfg); +end_init_5: + sample_common_svp_vpss_unbind_vdec(vpss_grp_cnt, SAMPLE_SVP_VDEC_CHN_0); +end_init_4: + sample_common_svp_vpss_detach_vb(media_cfg, vpss_grp_cnt); +end_init_3: + sample_common_svp_stop_vpss(vpss_grp_cnt, media_cfg->chn_num); +end_init_2: + sample_common_svp_stop_vdec(SAMPLE_SVP_VDEC_CHN_NUM); +end_init_1: + sample_common_svp_destroy_vb(media_cfg); + return ret; +} + +td_void sample_common_svp_destroy_vb_stop_vdec_vpss_vo(vdec_thread_param *vdec_send, pthread_t *vdec_thread, + ot_sample_svp_media_cfg *media_cfg, sample_vo_cfg *vo_cfg) +{ + const td_s32 vpss_grp_cnt = 1; + + sample_svp_check_exps_return_void(media_cfg == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "media_cfg is NULL!\n"); + + sample_svp_check_exps_return_void((media_cfg->chn_num == 0) || (media_cfg->chn_num > OT_SVP_MAX_VPSS_CHN_NUM), + SAMPLE_SVP_ERR_LEVEL_ERROR, "media_cfg->chn_num must be [1, %u]!\n", OT_SVP_MAX_VPSS_CHN_NUM); + + sample_common_svp_stop_venc(&(media_cfg->svp_switch)); + + sample_comm_vdec_stop_send_stream(SAMPLE_SVP_VDEC_CHN_NUM, vdec_send, vdec_thread, SAMPLE_SVP_VDEC_CHN_NUM, + SAMPLE_SVP_VDEC_CHN_NUM); + sample_common_svp_stop_vo(&(media_cfg->svp_switch), vo_cfg); + sample_common_svp_vpss_unbind_vdec(vpss_grp_cnt, SAMPLE_SVP_VDEC_CHN_0); + sample_common_svp_vpss_detach_vb(media_cfg, vpss_grp_cnt); + sample_common_svp_stop_vpss(vpss_grp_cnt, media_cfg->chn_num); + sample_common_svp_stop_vdec(SAMPLE_SVP_VDEC_CHN_NUM); + sample_common_svp_destroy_vb(media_cfg); +} + +td_s32 sample_common_svp_venc_vo_send_stream(const ot_sample_svp_switch *vo_venc_switch, ot_venc_chn venc_chn, + ot_vo_layer vo_layer, ot_vo_chn vo_chn, const ot_video_frame_info *frame) +{ + td_s32 ret = OT_INVALID_VALUE; + + sample_svp_check_exps_return((vo_venc_switch == TD_NULL || frame == TD_NULL), ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "vo_venc_switch is NULL!\n"); + if (vo_venc_switch->is_venc_open) { + ret = ss_mpi_venc_send_frame(venc_chn, frame, OT_SVP_TIMEOUT); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),ss_mpi_venc_send_frame failed!\n", ret); + } + if (vo_venc_switch->is_vo_open) { + ret = ss_mpi_vo_send_frame(vo_layer, vo_chn, frame, OT_SVP_TIMEOUT); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),ss_mpi_vo_send_frame failed!\n", ret); + } + return TD_SUCCESS; +} + +static td_s32 sample_common_svp_npu_get_pic_size(ot_sample_svp_media_cfg *media_cfg) +{ + td_s32 ret; + ret = sample_comm_sys_get_pic_size(media_cfg->pic_type[0], &media_cfg->pic_size[0]); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_comm_sys_get_pic_size failed,Error(%#x)!\n", ret); + return TD_SUCCESS; +} + +/* + * function : Start Vi/Vpss/Vo + */ +td_s32 sample_common_svp_npu_start_vi_vpss_vo(sample_vi_cfg *vi_cfg, ot_sample_svp_media_cfg *media_cfg, + sample_vo_cfg *vo_cfg) +{ + td_s32 ret; + const td_s32 vpss_grp_cnt = 1; + sample_sns_type sns_type = SENSOR0_TYPE; + + ret = sample_common_svp_get_pic_type_by_sns_type(sns_type, media_cfg->pic_type, OT_SVP_MAX_VPSS_CHN_NUM); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "sample_common_svp_get_pic_type_by_sns_type failed!\n"); + sample_comm_vi_get_default_vi_cfg(sns_type, vi_cfg); + + ret = sample_common_svp_npu_get_pic_size(media_cfg); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x):sample_common_svp_npu_get_pic_size failed!\n", ret); + + /* step 1: Init vb */ + ret = sample_common_svp_create_vb(media_cfg); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_create_vb failed!\n", ret); + + /* step 2: Start vi */ + ret = sample_comm_vi_start_vi(vi_cfg); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_comm_vi_start_vi failed!\n", ret); + + /* step 3: Bind vpss to vi */ + ret = sample_common_svp_vi_bind_multi_vpss(vpss_grp_cnt, 1, 1); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_2, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_vi_bind_multi_vpss failed!\n", ret); + + /* step 4: Start vpss */ + ret = sample_common_svp_start_vpss(vpss_grp_cnt, media_cfg->pic_size, media_cfg->chn_num); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_3, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vpss failed!\n", ret); + + /* step 5: attach vb */ + ret = sample_common_svp_vpss_attach_vb(media_cfg, vpss_grp_cnt); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_4, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vpss failed!\n", ret); + + /* step 6: Start vo */ + ret = sample_common_svp_start_vo(&(media_cfg->svp_switch), vo_cfg); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end_init_5, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_start_vo failed!\n", ret); + + return ret; + +end_init_5: + sample_common_svp_vpss_detach_vb(media_cfg, vpss_grp_cnt); +end_init_4: + sample_common_svp_stop_vpss(vpss_grp_cnt, media_cfg->chn_num); +end_init_3: + sample_common_svp_vi_unbind_multi_vpss(vpss_grp_cnt, 1, 1); +end_init_2: + sample_comm_vi_stop_vi(vi_cfg); +end_init_1: + sample_common_svp_destroy_vb(media_cfg); + return ret; +} + +td_void sample_common_svp_destroy_vb_stop_vi_vpss_vo(sample_vi_cfg *vi_cfg, ot_sample_svp_media_cfg *media_cfg, + sample_vo_cfg *vo_cfg) +{ + const td_s32 vpss_grp_cnt = 1; + + sample_svp_check_exps_return_void(media_cfg == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "media_cfg is NULL!\n"); + + sample_svp_check_exps_return_void((media_cfg->chn_num == 0) || (media_cfg->chn_num > OT_SVP_MAX_VPSS_CHN_NUM), + SAMPLE_SVP_ERR_LEVEL_ERROR, "media_cfg->chn_num must be [1, %u]!\n", OT_SVP_MAX_VPSS_CHN_NUM); + + sample_common_svp_stop_vo(&(media_cfg->svp_switch), vo_cfg); + sample_common_svp_vpss_detach_vb(media_cfg, vpss_grp_cnt); + sample_common_svp_stop_vpss(vpss_grp_cnt, media_cfg->chn_num); + sample_common_svp_vi_unbind_multi_vpss(vpss_grp_cnt, 1, 1); + sample_comm_vi_stop_vi(vi_cfg); + sample_common_svp_destroy_vb(media_cfg); +} diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp.h b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp.h new file mode 100755 index 0000000000000000000000000000000000000000..4ba556b17669a3b834ffea68f50343a60fc6d3ea --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SAMPLE_COMMON_SVP_H +#define SAMPLE_COMMON_SVP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ss_mpi_sys.h" +#include "ot_common.h" +#include "ot_common_svp.h" +#include "sample_comm.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* __cplusplus */ + +#define OT_SVP_RECT_NUM 64 +#define OT_POINT_NUM 4 +#define OT_SVP_MAX_VPSS_CHN_NUM 2 +#define OT_SVP_TIMEOUT 2000 + +typedef enum { + SAMPLE_SVP_ERR_LEVEL_DEBUG = 0x0, /* debug-level */ + SAMPLE_SVP_ERR_LEVEL_INFO = 0x1, /* informational */ + SAMPLE_SVP_ERR_LEVEL_NOTICE = 0x2, /* normal but significant condition */ + SAMPLE_SVP_ERR_LEVEL_WARNING = 0x3, /* warning conditions */ + SAMPLE_SVP_ERR_LEVEL_ERROR = 0x4, /* error conditions */ + SAMPLE_SVP_ERR_LEVEL_CRIT = 0x5, /* critical conditions */ + SAMPLE_SVP_ERR_LEVEL_ALERT = 0x6, /* action must be taken immediately */ + SAMPLE_SVP_ERR_LEVEL_FATAL = 0x7, /* just for compatibility with previous version */ + + SAMPLE_SVP_ERR_LEVEL_BUTT +} sample_svp_err_level; + +typedef struct { + ot_point point[OT_POINT_NUM]; + td_float score; + td_u16 class_id; +} ot_sample_svp_rect; + +typedef struct { + td_u16 num; + ot_sample_svp_rect rect[OT_SVP_RECT_NUM]; +} ot_sample_svp_rect_info; + +typedef struct { + td_bool is_venc_open; + td_bool is_vo_open; +} ot_sample_svp_switch; + +typedef struct { + ot_sample_svp_switch svp_switch; + ot_size pic_size[OT_SVP_MAX_VPSS_CHN_NUM]; + ot_pic_size pic_type[OT_SVP_MAX_VPSS_CHN_NUM]; + ot_vb_pool vb_pool[OT_SVP_MAX_VPSS_CHN_NUM]; + td_u32 chn_num; +} ot_sample_svp_media_cfg; + +#define sample_svp_printf(level_str, msg, ...) \ +do { \ + fprintf(stderr, "[level]:%s,[func]:%s [line]:%d [info]:"msg, level_str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ +} while (0) + +#define sample_svp_printf_red(level_str, msg, ...) \ +do { \ + fprintf(stderr, "\033[0;31m [level]:%s,[func]:%s [line]:%d [info]:"msg"\033[0;39m\n", level_str, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__); \ +} while (0) +/* system is unusable */ +#define sample_svp_trace_fatal(msg, ...) sample_svp_printf_red("Fatal", msg, ##__VA_ARGS__) +/* action must be taken immediately */ +#define sample_svp_trace_alert(msg, ...) sample_svp_printf_red("Alert", msg, ##__VA_ARGS__) +/* critical conditions */ +#define sample_svp_trace_critical(msg, ...) sample_svp_printf_red("Critical", msg, ##__VA_ARGS__) +/* error conditions */ +#define sample_svp_trace_err(msg, ...) sample_svp_printf_red("Error", msg, ##__VA_ARGS__) +/* warning conditions */ +#define sample_svp_trace_warning(msg, ...) sample_svp_printf("Warning", msg, ##__VA_ARGS__) +/* normal but significant condition */ +#define sample_svp_trace_notic(msg, ...) sample_svp_printf("Notice", msg, ##__VA_ARGS__) +/* informational */ +#define sample_svp_trace_info(msg, ...) sample_svp_printf("Info", msg, ##__VA_ARGS__) +/* debug-level messages */ +#define sample_svp_trace_debug(msg, ...) sample_svp_printf("Debug", msg, ##__VA_ARGS__) + +/* exps is true, goto */ +#define sample_svp_check_exps_goto(exps, label, level, msg, ...) \ +do { \ + if ((exps)) { \ + sample_svp_trace_err(msg, ## __VA_ARGS__); \ + goto label; \ + } \ +} while (0) +/* exps is true, return td_void */ +#define sample_svp_check_exps_return_void(exps, level, msg, ...) \ +do { \ + if ((exps)) { \ + sample_svp_trace_err(msg, ##__VA_ARGS__); \ + return; \ + } \ +} while (0) +/* exps is true, return ret */ +#define sample_svp_check_exps_return(exps, ret, level, msg, ...) \ +do { \ + if ((exps)) { \ + sample_svp_trace_err(msg, ##__VA_ARGS__); \ + return (ret); \ + } \ +} while (0) \ +/* exps is true, trace */ +#define sample_svp_check_exps_trace(exps, level, msg, ...) \ +do { \ + if ((exps)) { \ + sample_svp_trace_err(msg, ##__VA_ARGS__); \ + } \ +} while (0) + +#define sample_svp_check_exps_continue(exps, level, msg, ...) \ +do { \ + if ((exps)) { \ + sample_svp_trace_err(msg, ##__VA_ARGS__); \ + continue; \ + } \ +} while (0) \ + +/* exps is not success, trace */ +#define sample_svp_check_failed_trace(exps, level, msg, ...) \ +do { \ + if ((exps) != TD_SUCCESS) { \ + sample_svp_trace_err(msg, ##__VA_ARGS__); \ + } \ +} while (0) + +/* exps is not success, goto */ +#define sample_svp_check_failed_goto(exps, label, level, msg, ...) \ +do { \ + if ((exps) != TD_SUCCESS) { \ + sample_svp_trace_err(msg, ## __VA_ARGS__); \ + goto label; \ + } \ +} while (0) \ + +/* exps is not sucecss, return */ +#define sample_svp_check_failed_return(exps, ret, level, msg, ...) \ +do { \ + if ((exps) != TD_SUCCESS) { \ + sample_svp_trace_err(msg, ##__VA_ARGS__); \ + return (ret); \ + } \ +} while (0) + +/* exps is not equal to success, goto with level SAMPLE_SVP_ERR_LEVEL_ERROR */ +#define sample_svp_check_failed_err_level_goto(exps, label, msg, ...) \ +do { \ + if ((exps) != TD_SUCCESS) { \ + sample_svp_trace_err(msg, ## __VA_ARGS__); \ + goto label; \ + } \ +} while (0) + +/* exps is not equal to success, return with level SAMPLE_SVP_ERR_LEVEL_ERROR */ +#define sample_svp_check_failed_err_level_return(exps, ret, msg, ...) \ +do { \ + if ((exps) != TD_SUCCESS) { \ + sample_svp_trace_err(msg, ## __VA_ARGS__); \ + return (ret); \ + } \ +} while (0) + +/* exps is not equal success, trace with level SAMPLE_SVP_ERR_LEVEL_ERROR */ +#define sample_svp_check_failed_err_level_trace(exps, msg, ...) \ +do { \ + if ((exps) != TD_SUCCESS) { \ + sample_svp_trace_err(msg, ##__VA_ARGS__); \ + } \ +} while (0) + +#define sample_svp_pause() \ +do { \ + printf("---------------press Enter key to exit!---------------\n"); \ + (void)getchar(); \ +} while (0) + +#define SAMPLE_SVP_VB_POOL_NUM 2 +#define SAMPLE_SVP_ALIGN_16 16 +#define SAMPLE_SVP_ALIGN_32 32 +#define SAMPLE_SVP_D1_PAL_HEIGHT 576 +#define SAMPLE_SVP_D1_PAL_WIDTH 704 +#define sample_svp_convert_addr_to_ptr(type, addr) ((type *)(td_uintptr_t)(addr)) +#define sample_svp_convert_ptr_to_addr(type, addr) ((type)(td_uintptr_t)(addr)) + +/* free mmz */ +#define sample_svp_mmz_free(phys, virt) \ +do { \ + if (((phys) != 0) && ((virt) != 0)) { \ + ss_mpi_sys_mmz_free((td_phys_addr_t)(phys), (td_void*)(td_uintptr_t)(virt)); \ + (phys) = 0; \ + (virt) = 0; \ + } \ +} while (0) + +#define sample_svp_close_file(fp) \ +do { \ + if ((fp) != TD_NULL) { \ + fclose((fp)); \ + (fp) = TD_NULL; \ + } \ +} while (0) + +/* System init */ +td_s32 sample_common_svp_check_sys_init(td_bool vi_en); + +/* System exit */ +td_void sample_common_svp_check_sys_exit(td_void); + +/* Align */ +td_u32 sample_common_svp_align(td_u32 size, td_u16 align); + +/* Create mem info */ +td_s32 sample_common_svp_create_mem_info(ot_svp_mem_info *mem_info, td_u32 size, td_u32 addr_offsset); + +/* Destory mem info */ +td_void sample_common_svp_destroy_mem_info(ot_svp_mem_info *mem_info, td_u32 addr_offsset); + +/* Malloc memory */ +td_s32 sample_common_svp_malloc_mem(td_char *mmb, td_char *zone, td_phys_addr_t *phys_addr, + td_void **virt_addr, td_u32 size); + +/* Malloc memory with cached */ +td_s32 sample_common_svp_malloc_cached(td_char *mmb, td_char *zone, td_phys_addr_t *phys_addr, + td_void **virt_addr, td_u32 size); + +/* Fulsh cached */ +td_s32 sample_common_svp_flush_cache(td_phys_addr_t phys_addr, td_void *virt_addr, td_u32 size); + +/* function : Call vgs to fill rect */ +td_s32 sample_common_svp_vgs_fill_rect(const ot_video_frame_info *frame_info, + ot_sample_svp_rect_info *rect, td_u32 color); + +/* function : Start Vi/Vpss/Venc/Vo */ +td_s32 sample_common_svp_start_vi_vpss_venc_vo(sample_vi_cfg *vi_config, + ot_sample_svp_switch *switch_ptr, ot_pic_size *ext_pic_size_type); + +/* function : Stop Vi/Vpss/Venc/Vo */ +td_void sample_common_svp_stop_vi_vpss_venc_vo(sample_vi_cfg *vi_config, + ot_sample_svp_switch *switch_ptr); + +/* + * Start Vdec/Vpss/Vo + */ +td_s32 sample_common_svp_create_vb_start_vdec_vpss_vo(sample_vdec_attr *vdec_attr, + vdec_thread_param *vdec_send, pthread_t *vdec_thread, ot_sample_svp_media_cfg *media_cfg, + sample_vo_cfg *vo_cfg); +/* + * Stop Vdec/Vpss/Vo + */ +td_void sample_common_svp_destroy_vb_stop_vdec_vpss_vo(vdec_thread_param *vdec_send, + pthread_t *vdec_thread, ot_sample_svp_media_cfg *media_cfg, sample_vo_cfg *vo_cfg); +/* + * Send stream to venc/vo + */ +td_s32 sample_common_svp_venc_vo_send_stream(const ot_sample_svp_switch *vo_venc_switch, + ot_venc_chn venc_chn, ot_vo_layer vo_layer, ot_vo_chn vo_chn, const ot_video_frame_info *frame); + +td_s32 sample_common_svp_npu_start_vi_vpss_vo(sample_vi_cfg *vi_cfg, ot_sample_svp_media_cfg *media_cfg, + sample_vo_cfg *vo_cfg); + +td_void sample_common_svp_destroy_vb_stop_vi_vpss_vo(sample_vi_cfg *vi_cfg, ot_sample_svp_media_cfg *media_cfg, + sample_vo_cfg *vo_cfg); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ +#endif /* SAMPLE_COMMON_SVP_H */ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu.c b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu.c new file mode 100755 index 0000000000000000000000000000000000000000..64ae73c394907fe461c04bc7611bcce526affccf --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sample_common_svp_npu.h" +#include "ot_common.h" +#include "ot_common_svp.h" +#include "sample_comm.h" +#include "sample_common_svp.h" + +/* acl init */ + td_s32 sample_common_svp_npu_acl_init(const td_char *acl_config_path, td_s32 dev_id) +{ + svp_acl_rt_run_mode run_mode; + svp_acl_error ret; + /* svp acl init */ + ret = svp_acl_init(acl_config_path); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "acl init failed!\n"); + sample_svp_trace_info("svp acl init success!\n"); + /* open device */ + ret = svp_acl_rt_set_device(dev_id); + sample_svp_check_exps_goto(ret != SVP_ACL_SUCCESS, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "svp acl open device %d failed!\n", dev_id); + + sample_svp_trace_info("open device %d success!\n", dev_id); + /* get run mode */ + ret = svp_acl_rt_get_run_mode(&run_mode); + sample_svp_check_exps_goto(ret != SVP_ACL_SUCCESS, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "acl get run mode failed!\n"); + sample_svp_check_exps_goto(run_mode != SVP_ACL_DEVICE, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "run mode(%d) is not equal to %d!\n", run_mode, SVP_ACL_DEVICE); + + sample_svp_trace_info("get run mode success!\n"); + return TD_SUCCESS; +end_1: + (td_void)svp_acl_rt_reset_device(dev_id); +end_0: + (td_void)svp_acl_finalize(); + return TD_FAILURE; +} + +/* acl deinit */ +td_void sample_common_svp_npu_acl_deinit(td_s32 dev_id) +{ + svp_acl_error ret; + + ret = svp_acl_rt_reset_device(dev_id); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("reset device fail\n"); + } + sample_svp_trace_info("end to reset device is %d\n", dev_id); + + ret = svp_acl_finalize(); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("finalize acl fail\n"); + } + sample_svp_trace_info("end to finalize acl\n"); +} diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu.h b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu.h new file mode 100755 index 0000000000000000000000000000000000000000..79c1e54cf7bdc1f99e3b78d8719b1a8d79b97138 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLE_COMMON_SVP_NPU_H +#define SAMPLE_COMMON_SVP_NPU_H +#include "ot_type.h" +#include "svp_acl.h" +#include "svp_acl_mdl.h" +#include "xvp_common_osd.h" + +#define SAMPLE_SVP_NPU_MAX_THREAD_NUM 16 +#define SAMPLE_SVP_NPU_MAX_TASK_NUM 16 +#define SAMPLE_SVP_NPU_MAX_MODEL_NUM 1 +#define SAMPLE_SVP_NPU_EXTRA_INPUT_NUM 2 +#define SAMPLE_SVP_NPU_BYTE_BIT_NUM 8 +#define SAMPLE_SVP_NPU_SHOW_TOP_NUM 5 +#define SAMPLE_SVP_NPU_MAX_NAME_LEN 32 +#define SAMPLE_SVP_NPU_MAX_MEM_SIZE 0xFFFFFFFF +#define SAMPLE_SVP_NPU_RECT_LEFT_TOP 0 +#define SAMPLE_SVP_NPU_RECT_RIGHT_TOP 1 +#define SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM 2 +#define SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM 3 +#define SAMPLE_SVP_NPU_THRESHOLD_NUM 4 + +#define SAMPLE_SVP_NPU_RFCN_THRESHOLD_NUM 2 +#define SAMPLE_SVP_NPU_AICPU_WAIT_TIME 1000 +#define SAMPLE_SVP_NPU_RECT_COLOR 0x0000FF00 +#define SAMPLE_SVP_NPU_MILLIC_SEC 20000 +#define SAMPLE_SVP_NPU_IMG_THREE_CHN 3 +#define SAMPLE_SVP_NPU_DOUBLE 2 +#define SAMPLE_SVP_NPU_YOLO_CLASS_NUM 80 +#define SAMPLE_SVP_NPU_YOLO_CPU_OUT_NUM 3 +#define SAMPLE_SVP_NPU_YOLO_SCALE_SIZE 3 +#define SAMPLE_SVP_NPU_YOLO_OUT_PARM_NUM 85 +#define SAMPLE_SVP_NPU_YOLO_CLASS_MEMBER_NUM 6 +#define SAMPLE_SVP_NPU_YOLO_SCORE_THRESHOLE 0.5 + +typedef struct { + td_u32 model_id; + td_bool is_load_flag; + td_ulong model_mem_size; + td_void *model_mem_ptr; + svp_acl_mdl_desc *model_desc; + size_t input_num; + size_t output_num; + size_t dynamic_batch_idx; +} sample_svp_npu_model_info; + +typedef struct { + td_u32 max_batch_num; + td_u32 dynamic_batch_num; + td_u32 total_t; + td_bool is_cached; + td_u32 model_idx; +} sample_svp_npu_task_cfg; + +typedef struct { + sample_svp_npu_task_cfg cfg; + svp_acl_mdl_dataset *input_dataset; + svp_acl_mdl_dataset *output_dataset; + td_void *task_buf_ptr; + size_t task_buf_size; + size_t task_buf_stride; + td_void *work_buf_ptr; + size_t work_buf_size; + size_t work_buf_stride; +} sample_svp_npu_task_info; + +typedef struct { + td_void *work_buf_ptr; + size_t work_buf_size; + size_t work_buf_stride; +} sample_svp_npu_shared_work_buf; + +typedef struct { + td_float score; + td_u32 class_id; +} sample_svp_npu_top_n_result; + +typedef struct { + td_char *num_name; + td_char *roi_name; + td_bool has_background; + td_u32 roi_offset; + td_bool is_cpu_rpn; + td_u32 idx; +} sample_svp_npu_detection_info; + +typedef enum { + SAMPLE_SVP_NPU_RFCN = 0, + SAMPLE_SVP_NPU_YOLO = 1, + SAMPLE_SVP_NPU_HRNET = 2, + SAMPLE_SVP_NPU_MODEL_NAME_BUTT, +} svp_npu_model_name; + +typedef struct { + svp_npu_model_name model_name; + sample_svp_npu_detection_info *detection_info; + sample_mpp_osd_info mpp_osd_info; +} sample_svp_npu_thread_args; + +typedef struct { + td_char roi_num_name[SAMPLE_SVP_NPU_MAX_NAME_LEN]; + td_char roi_class_name[SAMPLE_SVP_NPU_MAX_NAME_LEN]; +} sample_svp_npu_roi_info; + +typedef struct { + td_float nms_threshold; + td_float score_threshold; + td_float min_height; + td_float min_width; + td_char *name; +} sample_svp_npu_threshold; + +typedef struct { + td_float score; + td_float xcenter; + td_float ycenter; + td_float w; + td_float h; + td_float class_id; +} sample_svp_npu_valid_box; + +typedef struct { + td_float lx; + td_float ly; + td_float rx; + td_float ry; + td_float score; + td_float class_id; + td_float area; +} sample_svp_npu_roi_box; + +typedef struct { + td_float *out_data; + size_t idx; + size_t w_stride_offset; + td_float score_thr; + td_u32 out_width; + td_u32 chn_step; + td_u32 out_height_idx; + td_u32 obj_score_offset; +} sample_svp_npu_detection_inner_param; + +/* acl init */ +td_s32 sample_common_svp_npu_acl_init(const td_char *acl_config_path, td_s32 dev_id); +/* acl deinit */ +td_void sample_common_svp_npu_acl_deinit(td_s32 dev_id); + +#endif diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu_model.c b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu_model.c new file mode 100755 index 0000000000000000000000000000000000000000..73f0ec1cddf77a0415a7e0453398548dd110cb51 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu_model.c @@ -0,0 +1,1500 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "svp_acl_rt.h" +#include "svp_acl_ext.h" +#include "sample_common_svp.h" +#include "sample_common_svp_npu_model.h" + +#define SAMPLE_SVP_NPU_H_DIM_IDX 2 +#define SAMPLE_SVP_NPU_W_DIM_IDX 3 +#define SAMPLE_SVP_NPU_DIM_NUM 4 +static sample_svp_npu_model_info g_svp_npu_model[SAMPLE_SVP_NPU_MAX_MODEL_NUM] = {0}; + +static td_s32 sample_svp_npu_get_model_base_info(td_u32 model_index) +{ + svp_acl_error ret; + + g_svp_npu_model[model_index].input_num = svp_acl_mdl_get_num_inputs(g_svp_npu_model[model_index].model_desc); + sample_svp_check_exps_return(g_svp_npu_model[model_index].input_num < SAMPLE_SVP_NPU_EXTRA_INPUT_NUM + 1, + TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "get input num failed!\n"); + + g_svp_npu_model[model_index].output_num = svp_acl_mdl_get_num_outputs(g_svp_npu_model[model_index].model_desc); + sample_svp_check_exps_return(g_svp_npu_model[model_index].output_num < 1, + TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "get output num failed!\n"); + + ret = svp_acl_mdl_get_input_index_by_name(g_svp_npu_model[model_index].model_desc, + SVP_ACL_DYNAMIC_TENSOR_NAME, &g_svp_npu_model[model_index].dynamic_batch_idx); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get dynamic batch idx failed, model id is %u, error code is %d!\n", model_index, ret); + + return TD_SUCCESS; +} + +static td_s32 sample_svp_npu_get_line_num_and_line_byte_num(const sample_svp_npu_task_info *task, td_u32 idx, + td_bool is_input, td_u32 *total_line_num, td_u32 *line_byte_num) +{ + td_s32 ret; + td_u32 i; + svp_acl_mdl_io_dims dims; + svp_acl_data_type data_type; + size_t data_size; + + if (is_input == TD_TRUE) { + ret = svp_acl_mdl_get_input_dims(g_svp_npu_model[task->cfg.model_idx].model_desc, idx, &dims); + } else { + ret = svp_acl_mdl_get_output_dims(g_svp_npu_model[task->cfg.model_idx].model_desc, idx, &dims); + } + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th input/output dims failed!\n", idx); + + if (is_input == TD_TRUE) { + data_type = svp_acl_mdl_get_input_data_type(g_svp_npu_model[task->cfg.model_idx].model_desc, idx); + } else { + data_type = svp_acl_mdl_get_output_data_type(g_svp_npu_model[task->cfg.model_idx].model_desc, idx); + } + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th input/output data type failed!\n", idx); + + data_size = svp_acl_data_type_size(data_type); + sample_svp_check_exps_return(data_size == 0, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "get data size failed!\n"); + + *line_byte_num = dims.dims[dims.dim_count - 1] * + ((data_size + SAMPLE_SVP_NPU_BYTE_BIT_NUM - 1) / SAMPLE_SVP_NPU_BYTE_BIT_NUM); + + *total_line_num = 1; + for (i = 0; i < dims.dim_count - 1; i++) { + *total_line_num *= dims.dims[i]; + } + /* lstm xt line num */ + if ((task->cfg.total_t != 0) && (idx == 0)) { + sample_svp_check_exps_return(task->cfg.total_t > dims.dims[0], TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "total t(%u) can't be greater than max total t(%ld)!\n", task->cfg.total_t, dims.dims[0]); + *total_line_num /= dims.dims[0]; + *total_line_num *= task->cfg.total_t; + } + return TD_SUCCESS; +} + +static td_s32 sample_svp_check_task_cfg(const sample_svp_npu_task_info *task) +{ + sample_svp_check_exps_return(task == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "task is NULL!\n"); + + sample_svp_check_exps_return(task->cfg.max_batch_num == 0, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "max_batch_num(%u) is 0!\n", task->cfg.max_batch_num); + + sample_svp_check_exps_return(task->cfg.dynamic_batch_num == 0, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "dynamic_batch_num(%u) is 0!\n", task->cfg.dynamic_batch_num); + + sample_svp_check_exps_return(task->cfg.total_t != 0 && task->cfg.dynamic_batch_num != 1, TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "dynamic_batch_num(%u) should be 1 when total_t(%u) is not 0!\n", + task->cfg.dynamic_batch_num, task->cfg.total_t); + + sample_svp_check_exps_return((task->cfg.is_cached != TD_TRUE && task->cfg.is_cached != TD_FALSE), TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "is_cached(%u) should be [%u, %u]!\n", task->cfg.is_cached, TD_FALSE, TD_TRUE); + + sample_svp_check_exps_return(task->cfg.model_idx >= SAMPLE_SVP_NPU_MAX_MODEL_NUM, TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "model_idx(%u) should be less than %u!\n", + task->cfg.model_idx, SAMPLE_SVP_NPU_MAX_MODEL_NUM); + + sample_svp_check_exps_return(g_svp_npu_model[task->cfg.model_idx].model_desc == TD_NULL, TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "%u-th model_desc is NULL!\n", task->cfg.model_idx); + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_get_input_data(const td_char *src[], td_u32 file_num, + const sample_svp_npu_task_info *task) +{ + td_s32 ret; + td_u32 i; + td_u32 line; + td_u32 total_line_num; + td_u32 line_byte_num; + td_char path[PATH_MAX] = { 0 }; + size_t stride; + size_t size; + size_t input_num; + FILE *fp = TD_NULL; + td_void *data = TD_NULL; + svp_acl_data_buffer *data_buffer = TD_NULL; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + sample_svp_check_exps_return(src == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "src is NULL!\n"); + + input_num = g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM; + sample_svp_check_exps_return(input_num != file_num, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "input file num(%u) should be equal to %lu!\n", file_num, input_num); + + for (i = 0; i < file_num; i++) { + sample_svp_check_exps_return(realpath(src[i], path) == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Invalid file!\n"); + + fp = fopen(path, "rb"); + sample_svp_check_exps_return(fp == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "open file failed!\n"); + + ret = sample_svp_npu_get_line_num_and_line_byte_num(task, i, TD_TRUE, &total_line_num, &line_byte_num); + sample_svp_check_exps_goto(ret != TD_SUCCESS, end, SAMPLE_SVP_ERR_LEVEL_ERROR, "get line num failed!\n"); + + data_buffer = svp_acl_mdl_get_dataset_buffer(task->input_dataset, i); + sample_svp_check_exps_goto(data_buffer == TD_NULL, end, SAMPLE_SVP_ERR_LEVEL_ERROR, "get data buffer NULL!\n"); + + data = svp_acl_get_data_buffer_addr(data_buffer); + sample_svp_check_exps_goto(data == TD_NULL, end, SAMPLE_SVP_ERR_LEVEL_ERROR, "get data addr NULL!\n"); + + stride = svp_acl_get_data_buffer_stride(data_buffer); + sample_svp_check_exps_goto(stride == 0, end, SAMPLE_SVP_ERR_LEVEL_ERROR, "get data stride failed!\n"); + + size = svp_acl_get_data_buffer_size(data_buffer); + sample_svp_check_exps_goto(size < (td_u64)task->cfg.dynamic_batch_num * total_line_num * stride, end, + SAMPLE_SVP_ERR_LEVEL_ERROR, "%u-th data buffer size(%lu) is less than needed(%llu)!\n", + i, size, (td_u64)task->cfg.dynamic_batch_num * total_line_num * stride); + + for (line = 0; line < task->cfg.dynamic_batch_num * total_line_num; line++) { + ret = fread(data + line * stride, line_byte_num, 1, fp); + sample_svp_check_exps_goto(ret != 1, end, SAMPLE_SVP_ERR_LEVEL_ERROR, "Read file failed!\n"); + } + if (task->cfg.is_cached == TD_TRUE) { + (td_void)svp_acl_rt_mem_flush(data, task->cfg.dynamic_batch_num * total_line_num * stride); + } + (td_void)fclose(fp); + } + return TD_SUCCESS; + +end: + if (fp != TD_NULL) { + (td_void)fclose(fp); + } + return TD_FAILURE; +} + +static td_s32 sample_svp_npu_read_model(const td_char *model_path, td_u32 model_index, td_bool is_cached) +{ + FILE *fp = TD_NULL; + td_s32 ret; + + /* Get model file size */ + fp = fopen(model_path, "rb"); + sample_svp_check_exps_return(fp == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "open model file failed, model file is %s!\n", model_path); + + ret = fseek(fp, 0L, SEEK_END); + sample_svp_check_exps_goto(ret == -1, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, "fseek failed!\n"); + + g_svp_npu_model[model_index].model_mem_size = ftell(fp); + sample_svp_check_exps_goto(g_svp_npu_model[model_index].model_mem_size <= 0, end_0, + SAMPLE_SVP_ERR_LEVEL_ERROR, "ftell failed!\n"); + + ret = fseek(fp, 0L, SEEK_SET); + sample_svp_check_exps_goto(ret == -1, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, "fseek failed!\n"); + + /* malloc model file mem */ + if (is_cached == TD_TRUE) { + ret = svp_acl_rt_malloc_cached(&g_svp_npu_model[model_index].model_mem_ptr, + g_svp_npu_model[model_index].model_mem_size, SVP_ACL_MEM_MALLOC_NORMAL_ONLY); + } else { + ret = svp_acl_rt_malloc(&g_svp_npu_model[model_index].model_mem_ptr, + g_svp_npu_model[model_index].model_mem_size, SVP_ACL_MEM_MALLOC_NORMAL_ONLY); + } + sample_svp_check_exps_goto(ret != SVP_ACL_SUCCESS, end_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "malloc mem failed, erroe code %d!\n", ret); + + ret = fread(g_svp_npu_model[model_index].model_mem_ptr, g_svp_npu_model[model_index].model_mem_size, 1, fp); + sample_svp_check_exps_goto(ret != 1, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, "read model file failed!\n"); + + if (is_cached == TD_TRUE) { + ret = svp_acl_rt_mem_flush(g_svp_npu_model[model_index].model_mem_ptr, + g_svp_npu_model[model_index].model_mem_size); + sample_svp_check_exps_goto(ret != SVP_ACL_SUCCESS, end_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "flush mem failed!, error code is %d\n", ret); + } + (td_void)fclose(fp); + return TD_SUCCESS; +end_1: + (td_void)svp_acl_rt_free(g_svp_npu_model[model_index].model_mem_ptr); +end_0: + (td_void)fclose(fp); + return TD_FAILURE; +} + +static td_s32 sample_svp_npu_create_desc(td_u32 model_index) +{ + svp_acl_error ret; + + g_svp_npu_model[model_index].model_desc = svp_acl_mdl_create_desc(); + sample_svp_check_exps_return(g_svp_npu_model[model_index].model_desc == TD_NULL, TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "create model description failed!\n"); + + ret = svp_acl_mdl_get_desc(g_svp_npu_model[model_index].model_desc, g_svp_npu_model[model_index].model_id); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "get model description failed, error code is %d!\n", ret); + + sample_svp_trace_info("create model description success!\n"); + + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_load_model(const td_char *model_path, td_u32 model_index, td_bool is_cached) +{ + td_s32 ret; + + sample_svp_check_exps_return(g_svp_npu_model[model_index].is_load_flag == TD_TRUE, TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "%u-th node has already loaded a model!\n", model_index); + + ret = sample_svp_npu_read_model(model_path, model_index, is_cached); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "query model failed, model file is %s!\n", model_path); + + ret = svp_acl_mdl_load_from_mem(g_svp_npu_model[model_index].model_mem_ptr, + g_svp_npu_model[model_index].model_mem_size, &g_svp_npu_model[model_index].model_id); + sample_svp_check_exps_goto(ret != SVP_ACL_SUCCESS, end_0, + SAMPLE_SVP_ERR_LEVEL_ERROR, "load model from mem failed, error code is %d!\n", ret); + + ret = sample_svp_npu_create_desc(model_index); + sample_svp_check_exps_goto(ret != SVP_ACL_SUCCESS, end_0, + SAMPLE_SVP_ERR_LEVEL_ERROR, "create desc failed, model file is %s!\n", model_path); + + ret = sample_svp_npu_get_model_base_info(model_index); + sample_svp_check_exps_goto(ret != SVP_ACL_SUCCESS, end_1, + SAMPLE_SVP_ERR_LEVEL_ERROR, "get model base info failed, model file is %s!\n", model_path); + + sample_svp_trace_info("load mem_size:%lu, id:%d!\n", g_svp_npu_model[model_index].model_mem_size, + g_svp_npu_model[model_index].model_id); + + g_svp_npu_model[model_index].is_load_flag = TD_TRUE; + sample_svp_trace_info("load model %s success!\n", model_path); + + return TD_SUCCESS; +end_1: + (td_void)svp_acl_mdl_destroy_desc(g_svp_npu_model[model_index].model_desc); + g_svp_npu_model[model_index].model_desc = TD_NULL; +end_0: + (td_void)svp_acl_rt_free(g_svp_npu_model[model_index].model_mem_ptr); + g_svp_npu_model[model_index].model_mem_ptr = TD_NULL; + g_svp_npu_model[model_index].model_mem_size = 0; + return TD_FAILURE; +} + +td_void sample_common_svp_npu_unload_model(td_u32 model_index) +{ + svp_acl_error ret; + + sample_svp_check_exps_return_void(g_svp_npu_model[model_index].is_load_flag != TD_TRUE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "%u-th node has not loaded a model!\n", model_index); + + ret = svp_acl_mdl_unload(g_svp_npu_model[model_index].model_id); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("unload model failed, model_id is %u, error code is %d!\n", + g_svp_npu_model[model_index].model_id, ret); + } + + if (g_svp_npu_model[model_index].model_desc != TD_NULL) { + (td_void)svp_acl_mdl_destroy_desc(g_svp_npu_model[model_index].model_desc); + g_svp_npu_model[model_index].model_desc = TD_NULL; + } + + if (g_svp_npu_model[model_index].model_mem_ptr != TD_NULL) { + (td_void)svp_acl_rt_free(g_svp_npu_model[model_index].model_mem_ptr); + g_svp_npu_model[model_index].model_mem_ptr = TD_NULL; + g_svp_npu_model[model_index].model_mem_size = 0; + } + + g_svp_npu_model[model_index].is_load_flag = TD_FALSE; + sample_svp_trace_info("unload model SUCCESS, model id is %u!\n", g_svp_npu_model[model_index].model_id); +} + +static td_s32 sample_svp_npu_malloc_mem(td_void **buffer, td_u32 buffer_size, td_bool is_cached) +{ + svp_acl_error ret; + + if (is_cached == TD_TRUE) { + ret = svp_acl_rt_malloc_cached(buffer, buffer_size, SVP_ACL_MEM_MALLOC_NORMAL_ONLY); + } else { + ret = svp_acl_rt_malloc(buffer, buffer_size, SVP_ACL_MEM_MALLOC_NORMAL_ONLY); + } + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "can't malloc buffer, size is %u, error code is %d!\n", buffer_size, ret); + + (td_void)memset_s(*buffer, buffer_size, 0, buffer_size); + if (is_cached == TD_TRUE) { + (td_void)svp_acl_rt_mem_flush(*buffer, buffer_size); + } + return ret; +} + +static td_void sample_svp_npu_destroy_data_buffer(svp_acl_data_buffer *input_data) +{ + td_void *data = svp_acl_get_data_buffer_addr(input_data); + (td_void)svp_acl_rt_free(data); + (td_void)svp_acl_destroy_data_buffer(input_data); +} + +static svp_acl_data_buffer *sample_common_svp_npu_create_input_data_buffer(sample_svp_npu_task_info *task, td_u32 idx) +{ + size_t buffer_size; + size_t stride; + td_void *input_buffer = TD_NULL; + svp_acl_data_buffer *input_data = TD_NULL; + + stride = svp_acl_mdl_get_input_default_stride(g_svp_npu_model[task->cfg.model_idx].model_desc, idx); + sample_svp_check_exps_return(stride == 0, input_data, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th input stride failed!\n", idx); + + buffer_size = svp_acl_mdl_get_input_size_by_index(g_svp_npu_model[task->cfg.model_idx].model_desc, idx) * + (td_u64)task->cfg.max_batch_num; + sample_svp_check_exps_return((buffer_size == 0 || buffer_size > SAMPLE_SVP_NPU_MAX_MEM_SIZE), input_data, + SAMPLE_SVP_ERR_LEVEL_ERROR, "buffer_size(%lu) can't be 0 and should be less than %u!\n", + buffer_size, SAMPLE_SVP_NPU_MAX_MEM_SIZE); + + if (sample_svp_npu_malloc_mem(&input_buffer, (td_u32)buffer_size, task->cfg.is_cached) != TD_SUCCESS) { + sample_svp_trace_err("%u-th input malloc mem failed!\n", idx); + return input_data; + } + + input_data = svp_acl_create_data_buffer(input_buffer, buffer_size, stride); + if (input_data == TD_NULL) { + sample_svp_trace_err("can't create %u-th input data buffer!\n", idx); + (td_void)svp_acl_rt_free(input_buffer); + return input_data; + } + if (idx == g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM) { + task->task_buf_ptr = input_buffer; + task->task_buf_size = buffer_size; + task->task_buf_stride = stride; + } else if (idx == g_svp_npu_model[task->cfg.model_idx].input_num - 1) { + task->work_buf_ptr = input_buffer; + task->work_buf_size = buffer_size; + task->work_buf_stride = stride; + } + return input_data; +} + +static svp_acl_data_buffer *sample_common_svp_npu_create_output_data_buffer(const sample_svp_npu_task_info *task, + td_u32 idx) +{ + size_t buffer_size; + size_t stride; + td_void *output_buffer = TD_NULL; + svp_acl_data_buffer *output_data = TD_NULL; + + stride = svp_acl_mdl_get_output_default_stride(g_svp_npu_model[task->cfg.model_idx].model_desc, idx); + sample_svp_check_exps_return(stride == 0, output_data, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th output stride failed!\n", idx); + + buffer_size = svp_acl_mdl_get_output_size_by_index(g_svp_npu_model[task->cfg.model_idx].model_desc, idx) * + (td_u64)task->cfg.max_batch_num; + sample_svp_check_exps_return((buffer_size == 0 || buffer_size > SAMPLE_SVP_NPU_MAX_MEM_SIZE), output_data, + SAMPLE_SVP_ERR_LEVEL_ERROR, "buffer_size(%lu) can't be 0 and should be less than %u!\n", + buffer_size, SAMPLE_SVP_NPU_MAX_MEM_SIZE); + + if (sample_svp_npu_malloc_mem(&output_buffer, buffer_size, task->cfg.is_cached) != TD_SUCCESS) { + sample_svp_trace_err("%u-th output malloc mem failed!\n", idx); + return output_data; + } + + output_data = svp_acl_create_data_buffer(output_buffer, buffer_size, stride); + if (output_data == TD_NULL) { + sample_svp_trace_err("can't create %u-th output data buffer!\n", idx); + (td_void)svp_acl_rt_free(output_buffer); + return output_data; + } + return output_data; +} + +td_s32 sample_common_svp_npu_create_input(sample_svp_npu_task_info *task) +{ + svp_acl_error ret; + td_u32 i; + svp_acl_data_buffer *input_data = TD_NULL; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + + task->input_dataset = svp_acl_mdl_create_dataset(); + sample_svp_check_exps_return(task->input_dataset == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "create input dataset failed!\n"); + + for (i = 0; i < g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM; i++) { + input_data = sample_common_svp_npu_create_input_data_buffer(task, i); + if (input_data == TD_NULL) { + sample_svp_trace_err("create %u-th input data buffer failed!\n", i); + (td_void)sample_common_svp_npu_destroy_input(task); + return TD_FAILURE; + } + + ret = svp_acl_mdl_add_dataset_buffer(task->input_dataset, input_data); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("add %u-th input data buffer failed!\n", i); + (td_void)sample_svp_npu_destroy_data_buffer(input_data); + (td_void)sample_common_svp_npu_destroy_input(task); + return TD_FAILURE; + } + } + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_create_output(sample_svp_npu_task_info *task) +{ + svp_acl_error ret; + td_u32 i; + svp_acl_data_buffer *output_data = TD_NULL; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + + task->output_dataset = svp_acl_mdl_create_dataset(); + sample_svp_check_exps_return(task->input_dataset == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "create output dataset failed!\n"); + + for (i = 0; i < g_svp_npu_model[task->cfg.model_idx].output_num; i++) { + output_data = sample_common_svp_npu_create_output_data_buffer(task, i); + if (output_data == TD_NULL) { + sample_svp_trace_err("create %u-th output data buffer failed!\n", i); + (td_void)sample_common_svp_npu_destroy_input(task); + return TD_FAILURE; + } + ret = svp_acl_mdl_add_dataset_buffer(task->output_dataset, output_data); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("add %u-th output data buffer failed!\n", i); + (td_void)sample_svp_npu_destroy_data_buffer(output_data); + (td_void)sample_common_svp_npu_destroy_output(task); + return TD_FAILURE; + } + } + + return TD_SUCCESS; +} + +td_void sample_common_svp_npu_destroy_input(sample_svp_npu_task_info *task) +{ + td_u32 i; + size_t input_num; + svp_acl_data_buffer *data_buffer = TD_NULL; + td_void *data = TD_NULL; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return; + } + + if (task->input_dataset == TD_NULL) { + return; + } + + input_num = svp_acl_mdl_get_dataset_num_buffers(task->input_dataset); + for (i = 0; i < input_num; i++) { + data_buffer = svp_acl_mdl_get_dataset_buffer(task->input_dataset, i); + if (i < g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM) { + data = svp_acl_get_data_buffer_addr(data_buffer); + (td_void)svp_acl_rt_free(data); + } + (td_void)svp_acl_destroy_data_buffer(data_buffer); + } + (td_void)svp_acl_mdl_destroy_dataset(task->input_dataset); + task->input_dataset = TD_NULL; +} + +td_void sample_common_svp_npu_destroy_output(sample_svp_npu_task_info *task) +{ + td_u32 i; + size_t output_num; + svp_acl_data_buffer *data_buffer = TD_NULL; + td_void *data = TD_NULL; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return; + } + + if (task->output_dataset == TD_NULL) { + return; + } + + output_num = svp_acl_mdl_get_dataset_num_buffers(task->output_dataset); + + for (i = 0; i < output_num; i++) { + data_buffer = svp_acl_mdl_get_dataset_buffer(task->output_dataset, i); + data = svp_acl_get_data_buffer_addr(data_buffer); + (td_void)svp_acl_rt_free(data); + (td_void)svp_acl_destroy_data_buffer(data_buffer); + } + + (td_void)svp_acl_mdl_destroy_dataset(task->output_dataset); + task->output_dataset = TD_NULL; +} + +td_void sample_common_svp_npu_destroy_task_buf(sample_svp_npu_task_info *task) +{ + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return; + } + + if (task->task_buf_ptr == TD_NULL) { + return; + } + (td_void)svp_acl_rt_free(task->task_buf_ptr); + task->task_buf_ptr = TD_NULL; + task->task_buf_stride = 0; + task->task_buf_size = 0; +} + +td_void sample_common_svp_npu_destroy_work_buf(sample_svp_npu_task_info *task) +{ + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return; + } + + if (task->work_buf_ptr == TD_NULL) { + return; + } + (td_void)svp_acl_rt_free(task->work_buf_ptr); + task->work_buf_ptr = TD_NULL; + task->work_buf_stride = 0; + task->work_buf_size = 0; +} + +td_s32 sample_common_svp_npu_create_task_buf(sample_svp_npu_task_info *task) +{ + size_t num; + svp_acl_data_buffer *task_buf = TD_NULL; + svp_acl_error ret; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + sample_svp_check_exps_return(task->input_dataset == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "input_dataset is NULL!\n"); + + num = svp_acl_mdl_get_dataset_num_buffers(task->input_dataset); + sample_svp_check_exps_return(num != g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM, + TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "num of data buffer(%lu) should be %lu when create task buf!\n", + num, g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM); + + task_buf = sample_common_svp_npu_create_input_data_buffer(task, + g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM); + sample_svp_check_exps_return(task_buf == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "create task buf failed!\n"); + + ret = svp_acl_mdl_add_dataset_buffer(task->input_dataset, task_buf); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("add task buf failed!\n"); + (td_void)sample_svp_npu_destroy_data_buffer(task_buf); + return TD_FAILURE; + } + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_create_work_buf(sample_svp_npu_task_info *task) +{ + size_t num; + svp_acl_data_buffer *work_buf = TD_NULL; + svp_acl_error ret; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + + sample_svp_check_exps_return(task->input_dataset == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "input_dataset is NULL!\n"); + + num = svp_acl_mdl_get_dataset_num_buffers(task->input_dataset); + sample_svp_check_exps_return(num != g_svp_npu_model[task->cfg.model_idx].input_num - 1, + TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "num of data buffer(%lu) should be %lu when create work buf!\n", + num, g_svp_npu_model[task->cfg.model_idx].input_num - 1); + + work_buf = sample_common_svp_npu_create_input_data_buffer(task, g_svp_npu_model[task->cfg.model_idx].input_num - 1); + sample_svp_check_exps_return(work_buf == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "create work buf failed!\n"); + + ret = svp_acl_mdl_add_dataset_buffer(task->input_dataset, work_buf); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("add work buf failed!\n"); + (td_void)sample_svp_npu_destroy_data_buffer(work_buf); + return TD_FAILURE; + } + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_get_work_buf_info(const sample_svp_npu_task_info *task, + td_u32 *work_buf_size, td_u32 *work_buf_stride) +{ + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + + *work_buf_stride = (td_u32)svp_acl_mdl_get_input_default_stride(g_svp_npu_model[task->cfg.model_idx].model_desc, + g_svp_npu_model[task->cfg.model_idx].input_num - 1); + if (*work_buf_stride == 0) { + sample_svp_trace_err("get work buf stride failed!\n"); + return TD_FAILURE; + } + + *work_buf_size = (td_u32)svp_acl_mdl_get_input_size_by_index(g_svp_npu_model[task->cfg.model_idx].model_desc, + g_svp_npu_model[task->cfg.model_idx].input_num - 1); + if (*work_buf_size == 0) { + sample_svp_trace_err("get work buf size failed!\n"); + return TD_FAILURE; + } + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_share_work_buf(const sample_svp_npu_shared_work_buf *shared_work_buf, + const sample_svp_npu_task_info *task) +{ + svp_acl_error ret; + svp_acl_data_buffer *work_buf = TD_NULL; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + + sample_svp_check_exps_return(shared_work_buf == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "shared_work_buf is NULL!\n"); + + sample_svp_check_exps_return(shared_work_buf->work_buf_ptr == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "work_buf_ptr is NULL!\n"); + + sample_svp_check_exps_return(task->work_buf_ptr != TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "task has created work buf!\n"); + + work_buf = svp_acl_create_data_buffer(shared_work_buf->work_buf_ptr, shared_work_buf->work_buf_size, + shared_work_buf->work_buf_stride); + sample_svp_check_exps_return(work_buf == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "create work buf failed!\n"); + + ret = svp_acl_mdl_add_dataset_buffer(task->input_dataset, work_buf); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("add work buf failed!\n"); + (td_void)svp_acl_destroy_data_buffer(work_buf); + return TD_FAILURE; + } + + return TD_SUCCESS; +} + +/* print the top n confidence values with indexes */ +static td_void sample_svp_npu_sort_output_result(const td_float *src, td_u32 src_len, + sample_svp_npu_top_n_result *dst, td_u32 dst_len) +{ + td_u32 i; + td_u32 j; + td_u32 index; + td_bool charge; + + for (i = 0; i < src_len; i++) { + charge = TD_FALSE; + + for (j = 0; j < dst_len; j++) { + if (src[i] > dst[j].score) { + index = j; + charge = TD_TRUE; + break; + } + } + + if (charge == TD_TRUE) { + for (j = dst_len - 1; j > index; j--) { + dst[j].score = dst[j - 1].score; + dst[j].class_id = dst[j - 1].class_id; + } + dst[index].score = src[i]; + dst[index].class_id = i; + } + } +} + +td_void sample_common_svp_npu_output_classification_result(const sample_svp_npu_task_info *task) +{ + svp_acl_data_buffer *data_buffer = TD_NULL; + td_void *data = TD_NULL; + td_u32 i; + td_u32 j; + td_u32 n; + svp_acl_error ret; + size_t stride; + svp_acl_mdl_io_dims dims; + sample_svp_npu_top_n_result top[SAMPLE_SVP_NPU_SHOW_TOP_NUM] = { 0 }; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return; + } + + sample_svp_check_exps_return_void(task->output_dataset == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "task->output_dataset is NULL!\n"); + + for (i = 0; i < svp_acl_mdl_get_dataset_num_buffers(task->output_dataset); i++) { + data_buffer = svp_acl_mdl_get_dataset_buffer(task->output_dataset, i); + sample_svp_check_exps_return_void(data_buffer == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th data buffer is NULL!\n", i); + + data = svp_acl_get_data_buffer_addr(data_buffer); + sample_svp_check_exps_return_void(data == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th data addr is NULL!\n", i); + + stride = svp_acl_get_data_buffer_stride(data_buffer); + sample_svp_check_exps_return_void(data == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th data stride is 0!\n", i); + + ret = svp_acl_mdl_get_output_dims(g_svp_npu_model[task->cfg.model_idx].model_desc, i, &dims); + sample_svp_check_exps_return_void(data == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th output dims failed, error code is %d!\n", i, ret); + + for (n = 0; n < task->cfg.dynamic_batch_num; n++) { + (td_void)sample_svp_npu_sort_output_result(data, (td_u32)dims.dims[dims.dim_count - 1], + top, SAMPLE_SVP_NPU_SHOW_TOP_NUM); + sample_svp_trace_info("%u-th batch result:\n", n); + for (j = 0; j < SAMPLE_SVP_NPU_SHOW_TOP_NUM; j++) { + sample_svp_trace_info("top %d: value[%lf], class_id[%u]!\n", j, top[j].score, top[j].class_id); + } + data += stride; + (td_void)memset_s(top, sizeof(top), 0, sizeof(top)); + } + } + + sample_svp_trace_info("output data success!\n"); +} + +td_s32 sample_common_svp_npu_set_dynamic_batch(const sample_svp_npu_task_info *task) +{ + svp_acl_error ret; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + ret = svp_acl_mdl_set_dynamic_batch_size(g_svp_npu_model[task->cfg.model_idx].model_id, + task->input_dataset, g_svp_npu_model[task->cfg.model_idx].dynamic_batch_idx, task->cfg.dynamic_batch_num); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "set dynamic batch size failed, model id is %u, error code is %d!\n", + g_svp_npu_model[task->cfg.model_idx].model_id, ret); + + if (task->cfg.total_t != 0) { + ret = svp_acl_mdl_set_total_t(g_svp_npu_model[task->cfg.model_idx].model_id, + task->input_dataset, task->cfg.total_t); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "set total_t failed, model id is %u, error code is %d!\n", + g_svp_npu_model[task->cfg.model_idx].model_id, ret); + } + + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_model_execute(const sample_svp_npu_task_info *task) +{ + svp_acl_data_buffer *data_buffer = TD_NULL; + td_void *data = TD_NULL; + size_t size; + td_u32 i; + svp_acl_error ret; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + + ret = svp_acl_mdl_execute(g_svp_npu_model[task->cfg.model_idx].model_id, task->input_dataset, task->output_dataset); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "svp_acl_mdl_execute failed, model_id is %u, error code is %d!\n", + g_svp_npu_model[task->cfg.model_idx].model_id, ret); + + if (task->cfg.is_cached == TD_TRUE) { + for (i = 0; i < g_svp_npu_model[task->cfg.model_idx].output_num; i++) { + data_buffer = svp_acl_mdl_get_dataset_buffer(task->output_dataset, i); + sample_svp_check_exps_return(data_buffer == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th output data_buffer is NULL!\n", i); + + data = svp_acl_get_data_buffer_addr(data_buffer); + sample_svp_check_exps_return(data == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th output data is NULL!\n", i); + + size = svp_acl_get_data_buffer_size(data_buffer) / task->cfg.max_batch_num * task->cfg.dynamic_batch_num; + sample_svp_check_exps_return(size == 0, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th output data size is 0!\n", i); + + ret = svp_acl_rt_mem_flush(data, size); + sample_svp_check_exps_return(data_buffer == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "flush %u-th output data failed, error code is %d!\n", i, ret); + } + } + return ret; +} + +static td_void sample_svp_npu_dump_dataset(const sample_svp_npu_task_info *task, const td_char *file_name, + td_bool is_input) +{ + td_u32 i; + td_u32 line; + td_u32 total_line_num; + td_u32 line_byte_num; + td_u32 data_num; + svp_acl_error ret; + size_t size; + size_t stride; + svp_acl_data_buffer *data_buffer = TD_NULL; + svp_acl_mdl_dataset *dataset = TD_NULL; + td_void *data = TD_NULL; + FILE *fp = TD_NULL; + td_char name[SAMPLE_SVP_NPU_MAX_NAME_LEN] = {'\0'}; + + data_num = is_input == TD_TRUE ? g_svp_npu_model[task->cfg.model_idx].input_num - SAMPLE_SVP_NPU_EXTRA_INPUT_NUM : + g_svp_npu_model[task->cfg.model_idx].output_num; + dataset = is_input == TD_TRUE ? task->input_dataset : task->output_dataset; + + for (i = 0; i < data_num; i++) { + ret = sample_svp_npu_get_line_num_and_line_byte_num(task, i, is_input, &total_line_num, &line_byte_num); + sample_svp_check_exps_return_void(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get line num and line byte num failed!\n"); + + data_buffer = svp_acl_mdl_get_dataset_buffer(dataset, i); + sample_svp_check_exps_return_void(data_buffer == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th data_buffer failed!\n", i); + + data = svp_acl_get_data_buffer_addr(data_buffer); + sample_svp_check_exps_return_void(data == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th data addr failed!\n", i); + + stride = svp_acl_get_data_buffer_stride(data_buffer); + sample_svp_check_exps_return_void(stride == 0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th data stride failed!\n", i); + + size = svp_acl_get_data_buffer_size(data_buffer); + sample_svp_check_exps_return_void(size == 0, SAMPLE_SVP_ERR_LEVEL_ERROR, "get %u-th data size failed!\n", i); + + sample_svp_check_exps_return_void(size < (td_u64)task->cfg.dynamic_batch_num * total_line_num * stride, + SAMPLE_SVP_ERR_LEVEL_ERROR, "%u-th data buffer size(%lu) is less than needed(%llu)!\n", + i, size, (td_u64)task->cfg.dynamic_batch_num * total_line_num * stride); + + ret = snprintf_s(name, SAMPLE_SVP_NPU_MAX_NAME_LEN - 1, SAMPLE_SVP_NPU_MAX_NAME_LEN - 1, file_name, i); + sample_svp_check_exps_return_void(ret < 0, SAMPLE_SVP_ERR_LEVEL_ERROR, "create file name failed!\n"); + + fp = fopen(name, "wb"); + sample_svp_check_exps_return_void(fp == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "open file failed!\n"); + + for (line = 0; line < task->cfg.dynamic_batch_num * total_line_num; line++) { + ret = fwrite(data, line_byte_num, 1, fp); + if (ret != 1) { + fclose(fp); + sample_svp_check_exps_return_void(ret != 1, SAMPLE_SVP_ERR_LEVEL_ERROR, "write file failed!\n"); + } + data += stride; + } + (td_void)fclose(fp); + } +} + +td_void sample_common_svp_npu_dump_task_data(const sample_svp_npu_task_info *task) +{ + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return; + } + + sample_svp_check_exps_return_void(task->input_dataset == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "task->input_dataset is NULL!\n"); + sample_svp_check_exps_return_void(task->output_dataset == TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "task->input_dataset is NULL!\n"); + + (td_void)sample_svp_npu_dump_dataset(task, "input_%u.bin", TD_TRUE); + (td_void)sample_svp_npu_dump_dataset(task, "output_%u.bin", TD_FALSE); +} + +td_s32 sample_common_svp_npu_update_input_data_buffer_info(td_u8 *virt_addr, td_u32 size, td_u32 stride, td_u32 idx, + const sample_svp_npu_task_info *task) +{ + svp_acl_data_buffer *data_buffer = TD_NULL; + svp_acl_error ret; + + data_buffer = svp_acl_mdl_get_dataset_buffer(task->input_dataset, idx); + sample_svp_check_exps_return(data_buffer == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th data_buffer failed!\n", idx); + ret = svp_acl_update_data_buffer(data_buffer, (td_void *)virt_addr, size, stride); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "update data buffer failed!\n"); + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_get_input_data_buffer_info(const sample_svp_npu_task_info *task, td_u32 idx, + td_u8 **virt_addr, td_u32 *size, td_u32 *stride) +{ + svp_acl_data_buffer *data_buffer = TD_NULL; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + sample_svp_check_exps_return(virt_addr == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "virt_addr is NULL!\n"); + sample_svp_check_exps_return(size == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "size is NULL!\n"); + sample_svp_check_exps_return(stride == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "size is NULL!\n"); + + data_buffer = svp_acl_mdl_get_dataset_buffer(task->input_dataset, idx); + sample_svp_check_exps_return(data_buffer == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get 0-th data_buffer failed!\n"); + *size = (td_u32)svp_acl_get_data_buffer_size(data_buffer); + *stride = (td_u32)svp_acl_get_data_buffer_stride(data_buffer); + *virt_addr = (td_u8 *)svp_acl_get_data_buffer_addr(data_buffer); + return TD_SUCCESS; +} + +static td_s32 sample_svp_npu_get_roi_num(const sample_svp_npu_task_info *task, sample_svp_npu_detection_info *info, + ot_sample_svp_rect_info *rect_info) +{ + svp_acl_error ret; + size_t num_idx; + svp_acl_mdl_io_dims dims; + svp_acl_data_buffer *data_buffer = TD_NULL; + td_float *data = TD_NULL; + td_float total_num = 0.0; + td_u32 start = 0; + td_u32 i; + + ret = svp_acl_mdl_get_output_index_by_name(g_svp_npu_model[task->cfg.model_idx].model_desc, + info->num_name, &num_idx); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get num idx failed!\n"); + + ret = svp_acl_mdl_get_output_dims(g_svp_npu_model[task->cfg.model_idx].model_desc, num_idx, &dims); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get num dims failed!\n"); + + data_buffer = svp_acl_mdl_get_dataset_buffer(task->output_dataset, num_idx); + sample_svp_check_exps_return(data_buffer == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get num data_buffer is NULL!\n"); + + data = (td_float *)svp_acl_get_data_buffer_addr(data_buffer); + sample_svp_check_exps_return(data == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "get num data is NULL!\n"); + + if (info->has_background == TD_TRUE) { + info->roi_offset = (td_u32)(*data); + start++; + } + + for (i = start; i < dims.dims[dims.dim_count - 1]; i++) { + total_num += *(data + i); + } + rect_info->num = (td_u32)total_num; + return TD_SUCCESS; +} + +static td_s32 sample_svp_npu_get_roi(const sample_svp_npu_task_info *task, const sample_svp_npu_detection_info *info, + const ot_video_frame_info *proc_frame, const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) +{ + svp_acl_error ret; + size_t roi_idx; + size_t stride; + svp_acl_data_buffer *data_buffer = TD_NULL; + td_float *x_min = TD_NULL; + td_float *y_min = TD_NULL; + td_float *x_max = TD_NULL; + td_float *y_max = TD_NULL; + td_float *score = TD_NULL; + td_float *class_id = TD_NULL; + td_u32 roi_offset = info->roi_offset; + td_u32 i; + + ret = svp_acl_mdl_get_output_index_by_name(g_svp_npu_model[task->cfg.model_idx].model_desc, + info->roi_name, &roi_idx); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi idx failed!\n"); + + data_buffer = svp_acl_mdl_get_dataset_buffer(task->output_dataset, roi_idx); + sample_svp_check_exps_return(data_buffer == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi data_buffer is NULL!\n"); + + stride = svp_acl_get_data_buffer_stride(data_buffer); + sample_svp_check_exps_return(stride == 0, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "get roi stride is 0!\n"); + + x_min = (td_float *)svp_acl_get_data_buffer_addr(data_buffer); + sample_svp_check_exps_return(x_min == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "get roi data is NULL!\n"); + y_min = x_min + stride / sizeof(td_float); + x_max = y_min + stride / sizeof(td_float); + y_max = x_max + stride / sizeof(td_float); + score = y_max + stride / sizeof(td_float); + class_id = score + stride / sizeof(td_float); + + for (i = 0; i < rect_info->num; i++) { + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x = (td_u32)((td_float)x_min[roi_offset] / + proc_frame->video_frame.width * show_frame->video_frame.width) & (~1); + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].y = (td_u32)((td_float)y_min[roi_offset] / + proc_frame->video_frame.height * show_frame->video_frame.height) & (~1); + + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_TOP].x = (td_u32)((td_float)x_max[roi_offset] / + proc_frame->video_frame.width * show_frame->video_frame.width) & (~1); + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_TOP].y = + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].y; + + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].x = + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_TOP].x; + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y = (td_u32)((td_float)y_max[roi_offset] / + proc_frame->video_frame.height * show_frame->video_frame.height) & (~1); + + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].x = + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x; + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].y = + rect_info->rect[i].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y; + + rect_info->rect[i].score = (td_float)((td_float)score[roi_offset]); + rect_info->rect[i].class_id = (td_u16)((td_float)class_id[roi_offset]); + + roi_offset++; + } + return TD_SUCCESS; +} + +static td_float sample_svp_npu_calc_iou(const sample_svp_npu_roi_box* box1, const sample_svp_npu_roi_box* box2) +{ + td_float area1 = box1->area; + td_float area2 = box2->area; + td_float xx1 = (box1->lx > box2->lx) ? box1->lx : box2->lx; + td_float yy1 = (box1->ly > box2->ly) ? box1->ly : box2->ly; + td_float xx2 = (box1->rx < box2->rx) ? box1->rx : box2->rx; + td_float yy2 = (box1->ry < box2->ry) ? box1->ry : box2->ry; + td_float w = (0.0f > (xx2 - xx1 + 1)) ? 0.0f : (xx2 - xx1 + 1); + td_float h = (0.0f > (yy2 - yy1 + 1)) ? 0.0f : (yy2 - yy1 + 1); + td_float inter = w * h; + td_float ovr = inter /(area1 + area2 - inter); + return ovr; +} + +static td_void sample_svp_npu_multiclass_nms(sample_svp_npu_roi_box *roi_box, td_u32 *roi_box_num, + sample_svp_npu_valid_box* valid_box, td_u32 valid_box_num) +{ + float nms_thr = 0.45; /* 0.45: threshold of ROI */ + for (td_u32 i = 0; i < valid_box_num; i++) { + sample_svp_npu_valid_box *item = &valid_box[i]; + td_float box_x_center = item->xcenter; + td_float box_y_center = item->ycenter; + td_float box_width = item->w; + td_float box_height = item->h; + + td_float x1 = (box_x_center - box_width / 2); + td_float y1 = (box_y_center - box_height / 2); + td_float x2 = (box_x_center + box_width / 2); + td_float y2 = (box_y_center + box_height / 2); + td_float area = (x2 - x1 + 1) * (y2 - y1 + 1); + td_bool keep = TD_TRUE; + /* lx, ly, rx, ry, score, class id, area */ + sample_svp_npu_roi_box box = {x1, y1, x2, y2, item->score, item->class_id, area}; + for (td_u32 j = 0; j < *roi_box_num; j++) { + if (sample_svp_npu_calc_iou(&box, &roi_box[j]) > nms_thr) { + keep = TD_FALSE; + break; + } + } + if (keep) { + if (*roi_box_num >= OT_SVP_RECT_NUM) { + sample_svp_trace_err("roi_box_num [%u] is large than %u!\n", *roi_box_num, OT_SVP_RECT_NUM); + return; + } + roi_box[*roi_box_num].lx = box.lx; + roi_box[*roi_box_num].ly = box.ly; + roi_box[*roi_box_num].rx = box.rx; + roi_box[*roi_box_num].ry = box.ry; + roi_box[*roi_box_num].score = box.score; + roi_box[*roi_box_num].class_id = box.class_id; + roi_box[*roi_box_num].area = box.area; + *roi_box_num = *roi_box_num + 1; + } + } +} + +inline static td_float sample_svp_npu_sig_mod(td_float a) +{ + return 1.0f / (1.0f + exp(-a)); +} + +static td_void sample_svp_npu_get_max_score_and_idx(td_u32 obj_score_idx, td_u32 chn_step, const td_float* out_data, + td_float *max_cls_score, td_u32 *max_cls_id) +{ + td_u32 cls_score_idx = obj_score_idx + chn_step; + for (td_u32 c = 0; c < SAMPLE_SVP_NPU_YOLO_CLASS_NUM; c++) { + td_float cls_score_val = out_data[cls_score_idx]; + if (cls_score_val > *max_cls_score) { + *max_cls_score = cls_score_val; + *max_cls_id = c; + } + cls_score_idx += chn_step; + } +} +static td_u32 g_sample_svp_npu_anchor_grids[SAMPLE_SVP_NPU_YOLO_CPU_OUT_NUM][SAMPLE_SVP_NPU_YOLO_CLASS_MEMBER_NUM] = { + {116, 90, 156, 198, 373, 326}, + {30, 61, 62, 45, 59, 119}, + {10, 13, 16, 30, 33, 23} +}; + +static td_void sample_svp_npu_process_per_dectection_inner(const sample_svp_npu_detection_inner_param *inner_param, + td_float *grids_x, td_float *grids_y, sample_svp_npu_valid_box* valid_box, td_u32 *valid_box_num) +{ + td_float box_hieght; + td_u32 expanded_strides[SAMPLE_SVP_NPU_YOLO_CPU_OUT_NUM] = { 32, 16, 8 }; + td_u32 out_height_idx = inner_param->out_height_idx; + td_u32 chn_step = inner_param->chn_step; + td_float score_thr = inner_param->score_thr; + td_float *out_data = inner_param->out_data; + size_t w_stride_offset = inner_param->w_stride_offset; + td_u32 obj_score_offset = inner_param->obj_score_offset; + td_u32 offset = out_height_idx * inner_param->w_stride_offset; + for (td_u32 j = 0; j < inner_param->out_width; j++) { + for (td_u32 k = 0; k < SAMPLE_SVP_NPU_YOLO_SCALE_SIZE; k++) { + offset = j + out_height_idx * w_stride_offset + k * chn_step * SAMPLE_SVP_NPU_YOLO_OUT_PARM_NUM; + td_u32 obj_score_idx = offset + obj_score_offset; + td_float obj_score_val = sample_svp_npu_sig_mod(out_data[obj_score_idx]); + if (obj_score_val <= score_thr) { + continue; + } + if (*valid_box_num >= OT_SVP_RECT_NUM) { + sample_svp_trace_err("valid_box_num [%u] is large than %u!\n", *valid_box_num, OT_SVP_RECT_NUM); + return; + } + /* max score */ + td_float max_cls_score = 0.0f; + td_u32 max_cls_id = 0; + sample_svp_npu_get_max_score_and_idx(obj_score_idx, chn_step, out_data, &max_cls_score, &max_cls_id); + + td_float confidence_score = sample_svp_npu_sig_mod(max_cls_score) * obj_score_val; + if (confidence_score > score_thr) { + /* gen box info */ + td_u32 x_center_idx = offset; + td_u32 y_center_idx = x_center_idx + chn_step; + td_u32 box_width_idx = y_center_idx + chn_step; + td_u32 box_height_idx = box_width_idx + chn_step; + td_float x_center = (sample_svp_npu_sig_mod(out_data[x_center_idx]) * SAMPLE_SVP_NPU_DOUBLE + + grids_x[j]) * expanded_strides[inner_param->idx]; + td_float y_center = (sample_svp_npu_sig_mod(out_data[y_center_idx]) * SAMPLE_SVP_NPU_DOUBLE + + grids_y[out_height_idx]) * expanded_strides[inner_param->idx]; + td_float tmp_value = sample_svp_npu_sig_mod(out_data[box_width_idx]) * SAMPLE_SVP_NPU_DOUBLE; + td_float box_width = tmp_value * tmp_value * g_sample_svp_npu_anchor_grids[inner_param->idx][(k << 1)]; + tmp_value = sample_svp_npu_sig_mod(out_data[box_height_idx]) * SAMPLE_SVP_NPU_DOUBLE; + box_hieght = tmp_value * tmp_value * g_sample_svp_npu_anchor_grids[inner_param->idx][(k << 1) +1]; + valid_box[*valid_box_num].score = confidence_score; + valid_box[*valid_box_num].xcenter = x_center; + valid_box[*valid_box_num].ycenter = y_center; + valid_box[*valid_box_num].w = box_width; + valid_box[*valid_box_num].h = box_hieght; + valid_box[*valid_box_num].class_id = (td_float)max_cls_id; + *valid_box_num = *valid_box_num + 1; + } + } + } +} + +static td_void sample_svp_npu_process_per_dectection(const sample_svp_npu_task_info *task, td_u32 idx, + sample_svp_npu_valid_box* valid_box, td_u32 *valid_box_num) +{ + td_u32 out_height; + svp_acl_mdl_io_dims out_dims; + sample_svp_npu_detection_inner_param inner_param; + svp_acl_data_buffer* data_buffer = TD_NULL; + td_u32 h_sizes[SAMPLE_SVP_NPU_YOLO_CPU_OUT_NUM] = { 20, 40, 80 }; + td_u32 w_sizes[SAMPLE_SVP_NPU_YOLO_CPU_OUT_NUM] = { 20, 40, 80 }; + /* gen grids */ + td_float grids_x[SAMPLE_SVP_NPU_YOLO_CLASS_NUM] = {0}; + td_float grids_y[SAMPLE_SVP_NPU_YOLO_CLASS_NUM] = {0}; + + svp_acl_mdl_get_output_dims(g_svp_npu_model[task->cfg.model_idx].model_desc, idx, &out_dims); + data_buffer = svp_acl_mdl_get_dataset_buffer(task->output_dataset, idx); + out_height = out_dims.dims[out_dims.dim_count - SAMPLE_SVP_NPU_DOUBLE]; + inner_param.out_width = out_dims.dims[out_dims.dim_count - 1]; + if (out_height > SAMPLE_SVP_NPU_YOLO_CLASS_NUM || inner_param.out_width > SAMPLE_SVP_NPU_YOLO_CLASS_NUM) { + sample_svp_trace_err("out_width[%u] or out_width[%u] is large than %u!\n", + out_height, inner_param.out_width, SAMPLE_SVP_NPU_YOLO_CLASS_NUM); + return; + } + + inner_param.score_thr = SAMPLE_SVP_NPU_YOLO_SCORE_THRESHOLE; + inner_param.idx = idx; + inner_param.out_data = (td_float *)svp_acl_get_data_buffer_addr(data_buffer); + inner_param.w_stride_offset = + svp_acl_mdl_get_output_default_stride(g_svp_npu_model[task->cfg.model_idx].model_desc, idx) / sizeof(td_float); + inner_param.chn_step = out_height * inner_param.w_stride_offset; + + for (td_u32 i = 0; i < h_sizes[idx]; i++) { + grids_y[i] = i - SAMPLE_SVP_NPU_YOLO_SCORE_THRESHOLE; + } + for (td_u32 i = 0; i < w_sizes[idx]; i++) { + grids_x[i] = i - SAMPLE_SVP_NPU_YOLO_SCORE_THRESHOLE; + } + inner_param.obj_score_offset = sizeof(td_float) * inner_param.chn_step; + for (td_u32 i = 0; i < out_height; i++) { + inner_param.out_height_idx = i; + sample_svp_npu_process_per_dectection_inner(&inner_param, grids_x, grids_y, valid_box, valid_box_num); + } +} + +static td_void sample_svp_npu_filter_yolo_box(const sample_svp_npu_task_info *task, + sample_svp_npu_valid_box* valid_box, td_u32 *valid_box_num) +{ + td_u32 out_num = svp_acl_mdl_get_num_outputs(g_svp_npu_model[task->cfg.model_idx].model_desc); + if (out_num > SAMPLE_SVP_NPU_YOLO_CPU_OUT_NUM) { + sample_svp_trace_err("output num [%u] is large than 3!\n", out_num); + return; + } + + /* gen box */ + for (td_u32 n = 0; n < out_num; n++) { + sample_svp_npu_process_per_dectection(task, n, valid_box, valid_box_num); + } +} + +static td_void sample_svp_npu_fill_rect_info(const ot_video_frame_info *proc_frame, + const ot_video_frame_info *show_frame, const sample_svp_npu_roi_box *roi_box, + td_u32 roi_box_num, ot_sample_svp_rect_info *rect_info) +{ + td_u32 rect_num = 0; + td_float w_multiples = (td_float)show_frame->video_frame.width / (td_float)proc_frame->video_frame.width; + td_float h_multiples = (td_float)show_frame->video_frame.height / (td_float)proc_frame->video_frame.height; + for (td_u32 i = 0; i < roi_box_num; i++) { + if (roi_box[i].score > 1.0f || roi_box[i].score < 0.0f) { + continue; + } + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x = (td_u32)(roi_box[i].lx * w_multiples) & (~1); + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].y = (td_u32)(roi_box[i].ly * h_multiples) & (~1); + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_RIGHT_TOP].x = (td_u32)(roi_box[i].rx * w_multiples) & (~1); + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_RIGHT_TOP].y = + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].y; + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].x = + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_RIGHT_TOP].x; + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y = + (td_u32)(roi_box[i].ry * h_multiples) & (~1); + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].x = + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_LEFT_TOP].x; + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_LEFT_BOTTOM].y = + rect_info->rect[rect_num].point[SAMPLE_SVP_NPU_RECT_RIGHT_BOTTOM].y; + rect_num++; + } + rect_info->num = rect_num; +} + +static td_s32 cmp_valid_box(const void *item1, const void *item2) +{ + sample_svp_npu_valid_box *box1 = (sample_svp_npu_valid_box *)item1; + sample_svp_npu_valid_box *box2 = (sample_svp_npu_valid_box *)item2; + if (box1->score > box2->score) { + return 1; + } + return 0; +} + +static td_s32 cmp_roi_box(const void *item1, const void *item2) +{ + sample_svp_npu_roi_box *box1 = (sample_svp_npu_roi_box *)item1; + sample_svp_npu_roi_box *box2 = (sample_svp_npu_roi_box *)item2; + if (box1->class_id < box2->class_id) { + return 1; + } else if (box1->class_id == box2->class_id) { + return box1->score > box2->score; + } + return 0; +} + +static td_s32 sample_svp_npu_get_roi_by_cpu(const sample_svp_npu_task_info *task, + const sample_svp_npu_detection_info *info, const ot_video_frame_info *proc_frame, + const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) +{ + td_u32 valid_box_num = 0; + td_u32 roi_box_num = 0; + sample_svp_npu_valid_box valid_box[OT_SVP_RECT_NUM] = {0}; + sample_svp_npu_roi_box roi_box[OT_SVP_RECT_NUM] = {0}; + + sample_svp_npu_filter_yolo_box(task, valid_box, &valid_box_num); + qsort((td_void *)valid_box, valid_box_num, sizeof(sample_svp_npu_valid_box), cmp_valid_box); + + sample_svp_npu_multiclass_nms(roi_box, &roi_box_num, valid_box, valid_box_num); + if (roi_box_num == 0) { + sample_svp_trace_info("No target object is detected !!!\n"); + return TD_SUCCESS; + } + qsort((td_void *)roi_box, roi_box_num, sizeof(sample_svp_npu_roi_box), cmp_roi_box); + sample_svp_npu_fill_rect_info(proc_frame, show_frame, roi_box, roi_box_num, rect_info); + + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, + sample_svp_npu_detection_info *detection_info, const ot_video_frame_info *proc_frame, + const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) +{ + td_s32 ret; + td_u32 i; + td_float max_confidence = 0.0f; + td_u32 max_index = 0; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + sample_svp_check_exps_return(detection_info == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "detection_info is NULL!\n"); + sample_svp_check_exps_return(proc_frame == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "proc_frame is NULL!\n"); + sample_svp_check_exps_return(show_frame == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "show_frame is NULL!\n"); + sample_svp_check_exps_return(rect_info == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "rect_info is NULL!\n"); + + detection_info->roi_offset = 0; + ret = sample_svp_npu_get_roi_num(task, detection_info, rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi num failed!\n"); + + ret = sample_svp_npu_get_roi(task, detection_info, proc_frame, show_frame, rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi failed!\n"); + + // 新增部分:筛选置信度最高的矩形框 + if (rect_info->num > 0) { + // 1. 查找置信度最高的矩形框 + for (i = 0; i < rect_info->num; i++) { + if (rect_info->rect[i].score > max_confidence) { + max_confidence = rect_info->rect[i].score; + max_index = i; + } + } + + // 2. 只保留置信度最高的矩形框 + if (rect_info->num > 1) { + rect_info->rect[0] = rect_info->rect[max_index]; + rect_info->num = 1; + } + } + + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_roi_to_rect_cpu(const sample_svp_npu_task_info *task, + sample_svp_npu_detection_info *detection_info, const ot_video_frame_info *proc_frame, + const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info) +{ + td_s32 ret; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + sample_svp_check_exps_return(detection_info == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "detection_info is NULL!\n"); + sample_svp_check_exps_return(proc_frame == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "proc_frame is NULL!\n"); + sample_svp_check_exps_return(show_frame == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "show_frame is NULL!\n"); + sample_svp_check_exps_return(rect_info == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "rect_info is NULL!\n"); + + ret = sample_svp_npu_get_roi_by_cpu(task, detection_info, proc_frame, show_frame, rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi failed!\n"); + + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_set_threshold(sample_svp_npu_threshold threshold[], td_u32 threshold_num, + const sample_svp_npu_task_info *task) +{ + td_u32 i; + td_u32 n; + svp_acl_error ret; + svp_acl_data_buffer *data_buffer = TD_NULL; + td_float *data = TD_NULL; + size_t idx; + size_t size; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + sample_svp_check_exps_return(threshold == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "threshold is NULL!\n"); + sample_svp_check_exps_return(threshold_num == 0, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "threshold_num is 0!\n"); + + for (i = 0; i < threshold_num; i++) { + ret = svp_acl_mdl_get_input_index_by_name(g_svp_npu_model[task->cfg.model_idx].model_desc, + threshold[i].name, &idx); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi idx failed!\n"); + + data_buffer = svp_acl_mdl_get_dataset_buffer(task->input_dataset, idx); + sample_svp_check_exps_return(data_buffer == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi data_buffer is NULL!\n"); + + size = svp_acl_get_data_buffer_size(data_buffer); + sample_svp_check_exps_return(size < SAMPLE_SVP_NPU_THRESHOLD_NUM * sizeof(td_float), TD_FAILURE, + SAMPLE_SVP_ERR_LEVEL_ERROR, "get size(%lu) is less than %lu!\n", + size, SAMPLE_SVP_NPU_THRESHOLD_NUM * sizeof(td_float)); + + data = (td_float *)svp_acl_get_data_buffer_addr(data_buffer); + sample_svp_check_exps_return(data == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get roi data is NULL!\n"); + n = 0; + data[n++] = threshold[i].nms_threshold; + data[n++] = threshold[i].score_threshold; + data[n++] = threshold[i].min_height; + data[n++] = threshold[i].min_width; + } + return TD_SUCCESS; +} + +td_s32 sample_common_svp_npu_check_has_aicpu_task(const sample_svp_npu_task_info *task, td_bool *has_aicpu_task) +{ + td_u32 aicpu_task_num; + svp_acl_error ret; + + if (sample_svp_check_task_cfg(task) != TD_SUCCESS) { + sample_svp_trace_err("check task cfg failed!\n"); + return TD_FAILURE; + } + sample_svp_check_exps_return(has_aicpu_task == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "has_aicpu_task is NULL!\n"); + + ret = svp_acl_ext_get_mdl_aicpu_task_num(g_svp_npu_model[task->cfg.model_idx].model_id, &aicpu_task_num); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get aicpu task num failed, error code is %d!\n", ret); + + *has_aicpu_task = (aicpu_task_num == 0) ? TD_FALSE : TD_TRUE; + return TD_SUCCESS; +} + +sample_svp_npu_model_info* sample_common_svp_npu_get_model_info(td_u32 model_idx) +{ + sample_svp_check_exps_return(model_idx >= SAMPLE_SVP_NPU_MAX_MODEL_NUM, NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "model_idx(%u) must be [0, %u)!\n", model_idx, SAMPLE_SVP_NPU_MAX_MODEL_NUM); + return &g_svp_npu_model[model_idx]; +} + +td_s32 sample_common_svp_npu_get_input_resolution(td_u32 model_idx, td_u32 input_idx, + ot_size *pic_size) +{ + svp_acl_error ret; + svp_acl_mdl_io_dims dims = {0}; + + ret = svp_acl_mdl_get_input_dims(g_svp_npu_model[model_idx].model_desc, input_idx, &dims); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get num dims failed!\n"); + pic_size->height = dims.dims[dims.dim_count - SAMPLE_SVP_NPU_H_DIM_IDX]; // NCHW + pic_size->width = dims.dims[dims.dim_count - 1]; // NCHW + return TD_SUCCESS; +} diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu_model.h b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu_model.h new file mode 100755 index 0000000000000000000000000000000000000000..18ff9e359a4c3cf2345f9c98d1821a1dcc2b5e93 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_npu_model.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLE_COMMON_SVP_NPU_MODEL_H +#define SAMPLE_COMMON_SVP_NPU_MODEL_H +#include "ot_type.h" +#include "svp_acl_mdl.h" +#include "sample_common_svp.h" +#include "sample_common_svp_npu.h" + +td_s32 sample_common_svp_npu_get_input_data(const td_char *src[], td_u32 file_num, + const sample_svp_npu_task_info *task); + +td_s32 sample_common_svp_npu_load_model(const td_char *model_path, td_u32 model_index, td_bool is_cached); +td_void sample_common_svp_npu_unload_model(td_u32 model_index); + +td_s32 sample_common_svp_npu_create_input(sample_svp_npu_task_info *task); +td_s32 sample_common_svp_npu_create_output(sample_svp_npu_task_info *task); +td_void sample_common_svp_npu_destroy_input(sample_svp_npu_task_info *task); +td_void sample_common_svp_npu_destroy_output(sample_svp_npu_task_info *task); + +td_s32 sample_common_svp_npu_create_task_buf(sample_svp_npu_task_info *task); +td_s32 sample_common_svp_npu_create_work_buf(sample_svp_npu_task_info *task); +td_void sample_common_svp_npu_destroy_task_buf(sample_svp_npu_task_info *task); +td_void sample_common_svp_npu_destroy_work_buf(sample_svp_npu_task_info *task); + +td_s32 sample_common_svp_npu_get_work_buf_info(const sample_svp_npu_task_info *task, + td_u32 *work_buf_size, td_u32 *work_buf_stride); +td_s32 sample_common_svp_npu_share_work_buf(const sample_svp_npu_shared_work_buf *shared_work_buf, + const sample_svp_npu_task_info *task); + +td_s32 sample_common_svp_npu_set_dynamic_batch(const sample_svp_npu_task_info *task); +td_s32 sample_common_svp_npu_model_execute(const sample_svp_npu_task_info *task); +td_void sample_common_svp_npu_output_classification_result(const sample_svp_npu_task_info *task); + +td_void sample_common_svp_npu_dump_task_data(const sample_svp_npu_task_info *task); + +td_s32 sample_common_svp_npu_set_threshold(sample_svp_npu_threshold threshold[], td_u32 threshold_num, + const sample_svp_npu_task_info *task); + +td_s32 sample_common_svp_npu_roi_to_rect(const sample_svp_npu_task_info *task, + sample_svp_npu_detection_info *detection_info, const ot_video_frame_info *proc_frame, + const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info); + +td_s32 sample_common_svp_npu_roi_to_rect_cpu(const sample_svp_npu_task_info *task, + sample_svp_npu_detection_info *detection_info, const ot_video_frame_info *proc_frame, + const ot_video_frame_info *show_frame, ot_sample_svp_rect_info *rect_info); + +td_s32 sample_common_svp_npu_update_input_data_buffer_info(td_u8 *virt_addr, td_u32 size, td_u32 stride, td_u32 idx, + const sample_svp_npu_task_info *task); + +td_s32 sample_common_svp_npu_get_input_data_buffer_info(const sample_svp_npu_task_info *task, td_u32 idx, + td_u8 **virt_addr, td_u32 *size, td_u32 *stride); + +td_s32 sample_common_svp_npu_check_has_aicpu_task(const sample_svp_npu_task_info *task, td_bool *has_aicpu_task); + +sample_svp_npu_model_info* sample_common_svp_npu_get_model_info(td_u32 model_idx); + +td_s32 sample_common_svp_npu_get_input_resolution(td_u32 model_idx, td_u32 input_idx, + ot_size *pic_size); +#endif diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_osd.c b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_osd.c new file mode 100755 index 0000000000000000000000000000000000000000..cc1def3677c282f89006400bbc6b86793b0ce252 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_osd.c @@ -0,0 +1,193 @@ +/* + Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sample_comm.h" +#include "easy_log.h" +#include "xvp_common_osd.h" +#include "sample_common_svp_npu.h" + +#define OVERLAY_MIN_HANDLE 20 +#define BUFFER_SIZE 16 +#define CLASS_BUFFER_SIZE 10 +#define DOUBLE_OF_SIZE 2 +#define BACKGROUND_ALPHA 255 +#define OSD_BUFFER_SIZE 32 +#define WIDTH_OF_MIN 1920 +#define HEIGHT_OF_MIN 1080 +#define WIDTH_OF_MAX 2560 +#define HEIGHT_OF_MAX 1440 + +void sample_osd_region_init(ot_rgn_attr *region, ot_size img_size) +{ + td_s32 i; + region->type = OT_RGN_OVERLAYEX; + region->attr.overlay.canvas_num = 2; /* 2: canvas num */ + + for (i = 0; i < OT_RGN_CLUT_NUM; i++) { + region->attr.overlay.clut[i] = (td_u32)(0x000fff0f * (i + 1) * (i + 1)); + region->attr.overlay.clut[i] |= 0xff000000; + } + region->attr.overlay.pixel_format = OT_PIXEL_FORMAT_ARGB_1555; + region->attr.overlay.size.width = img_size.width * DOUBLE_OF_SIZE; + region->attr.overlay.size.height = img_size.height * DOUBLE_OF_SIZE; + region->attr.overlay.bg_color = 0xffff; +} + +void sample_osd_chn_attr_init(ot_rgn_chn_attr *chn_attr) +{ + chn_attr->type = OT_RGN_OVERLAYEX; + chn_attr->is_show = TD_TRUE; + chn_attr->attr.overlay_chn.bg_alpha = BACKGROUND_ALPHA; + chn_attr->attr.overlay_chn.fg_alpha = BACKGROUND_ALPHA; + chn_attr->attr.overlay_chn.qp_info.enable = TD_FALSE; + chn_attr->attr.overlay_chn.qp_info.is_abs_qp = TD_FALSE; + chn_attr->attr.overlay_chn.qp_info.qp_val = 0; + chn_attr->attr.overlay_chn.dst = OT_RGN_ATTACH_JPEG_MAIN; + chn_attr->attr.overlay_chn.layer = 0; +} + +void sample_osd_info_init(xvp_osd_info *osd_info, ot_rgn_attr region) +{ + osd_info->border_color = 0x0; + osd_info->font_color = SAMPLE_SVP_NPU_RECT_COLOR; + osd_info->factor = 2; /* 2: factor of osd info */ + osd_info->width = region.attr.overlay.size.width; + osd_info->height = region.attr.overlay.size.height; + osd_info->stride = region.attr.overlay.size.width; +} + +int sample_osd_init(sample_mpp_osd_info *mpp_osd_info) +{ + printf("sample_osd_init ...\r\n"); + td_s32 ret; + ot_rgn_attr region = {0}; + ot_mpp_chn chn = {0}; + ot_rgn_chn_attr chn_attr = {0}; + xvp_osd_info osd_info = {0}; + char osd_str[BUFFER_SIZE] = "scissors 0.00"; + unsigned char gb_str[BUFFER_SIZE] = {0}; + ot_size img_size = {BUFFER_SIZE}; + + chn.mod_id = OT_ID_VPSS; + chn.dev_id = 0; + chn.chn_id = 0; + + xvp_common_osd_utf8_to_gb2312((unsigned char *)osd_str, strlen(osd_str), gb_str); + xvp_common_osd_calculate_canvas_size(gb_str, 1, &img_size.width, &img_size.height); + printf("%s-%d l:%d w:%u h:%u\n", __func__, __LINE__, strlen(gb_str), img_size.width, img_size.height); + + sample_osd_region_init(®ion, img_size); + + ret = ss_mpi_rgn_create(mpp_osd_info->handle, ®ion); + if (ret != TD_SUCCESS) { + LOGE("ss_mpi_rgn_create failed with %#x!", ret); + } + + sample_osd_chn_attr_init(&chn_attr); + ret = ss_mpi_rgn_attach_to_chn(mpp_osd_info->handle, &chn, &chn_attr); + if (ret != TD_SUCCESS) { + LOGE("ss_mpi_rgn_attach_to_chn failed with %#x!", ret); + } + + sample_osd_info_init(&osd_info, region); + mpp_osd_info->chn = chn; + mpp_osd_info->chn_attr = chn_attr; + mpp_osd_info->osd_info = osd_info; + + xvp_common_osd_init(NULL); + + return 0; +} + +int sample_osd_exit(sample_mpp_osd_info *mpp_osd_info) +{ + printf("sample_osd_exit ...\r\n"); + td_s32 ret; + xvp_common_osd_exit(); + + ret = ss_mpi_rgn_detach_from_chn(mpp_osd_info->handle, &mpp_osd_info->chn); + if (ret != TD_SUCCESS) { + LOGE("ss_mpi_rgn_detach_from_chn failed with %#x!", ret); + } + + ret = ss_mpi_rgn_destroy(mpp_osd_info->handle); + if (ret != TD_SUCCESS) { + LOGE("ss_mpi_rgn_destroy failed with %#x!", ret); + } + + return 0; +} + +int sample_osd_draw_text(td_float score, td_u16 class_id, td_u16 x, td_u16 y, + sample_mpp_osd_info mpp_osd_info) +{ + printf("sample_osd_draw_text ...\r\n"); + td_s32 ret; + const char classes[][CLASS_BUFFER_SIZE] = {"梨子", "西瓜", "橙子", "香蕉", "苹果"}; + char osd_str[OSD_BUFFER_SIZE] = "西瓜 0.00"; + unsigned char gb_str[OSD_BUFFER_SIZE] = {0}; + ot_size img_size = {0}; + ot_bmp bitmap = {0}; + + bitmap.width = mpp_osd_info.osd_info.width; + bitmap.height = mpp_osd_info.osd_info.height; + bitmap.pixel_format = OT_PIXEL_FORMAT_ARGB_1555; + bitmap.data = (td_void*)malloc(bitmap.width * bitmap.height * DOUBLE_OF_SIZE); + + ret = snprintf(osd_str, sizeof(osd_str), "%s %0.2f", classes[class_id], score); + if (ret < 0) { + printf("%s:snprintf failed, ret:0x%x.\n", __FUNCTION__, ret); + } + memset_sp(bitmap.data, bitmap.width * bitmap.height * DOUBLE_OF_SIZE, 0x0, + bitmap.width * bitmap.height * DOUBLE_OF_SIZE); + memset_sp(gb_str, sizeof(gb_str), 0, sizeof(gb_str)); + xvp_common_osd_utf8_to_gb2312((unsigned char *)osd_str, strlen(osd_str), gb_str); + + xvp_common_osd_draw_text((unsigned char *)bitmap.data, gb_str, 0, 0, &mpp_osd_info.osd_info); + ret = ss_mpi_rgn_set_bmp(mpp_osd_info.handle, &bitmap); + if (ret != TD_SUCCESS) { + LOGE("ss_mpi_rgn_set_bmp failed with %#x!", ret); + } + int min_x = (int)(x * WIDTH_OF_MIN / WIDTH_OF_MAX); + int min_y = (int)(y * HEIGHT_OF_MIN / HEIGHT_OF_MAX); + + if ((min_x % DOUBLE_OF_SIZE) != 0) { + min_x = min_x + 1; + } + if ((min_y % DOUBLE_OF_SIZE) != 0) { + min_y = min_y + 1; + } + printf("min_x:%d, min_y:%d\r\n", min_x, min_y); + mpp_osd_info.chn_attr.attr.overlay_chn.point.x = min_x; + mpp_osd_info.chn_attr.attr.overlay_chn.point.y = min_y; + mpp_osd_info.chn_attr.is_show = TD_TRUE; + ss_mpi_rgn_set_display_attr(mpp_osd_info.handle, &mpp_osd_info.chn, &mpp_osd_info.chn_attr); + + if (bitmap.data != NULL) { + free(bitmap.data); + bitmap.data = NULL; + } + + return 0; +} + +int sample_osd_clean_text(sample_mpp_osd_info mpp_osd_info) +{ + ss_mpi_rgn_set_display_attr(mpp_osd_info.handle, &mpp_osd_info.chn, &mpp_osd_info.chn_attr); +} \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_osd.h b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_osd.h new file mode 100755 index 0000000000000000000000000000000000000000..3399494a4b8d190dc485a8503819fc845e798148 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/common/sample_common_svp_osd.h @@ -0,0 +1,18 @@ +#ifndef SAMPLE_COMMON_SVP_OSD_H +#define SAMPLE_COMMON_SVP_OSD_H +#include "xvp_common_osd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int sample_osd_init(sample_mpp_osd_info *mpp_osd_info); +int sample_osd_exit(sample_mpp_osd_info *mpp_osd_info); +int sample_osd_draw_text(td_float score, td_u16 class_id, td_u16 x, td_u16 y, sample_mpp_osd_info mpp_osd_info); +int sample_osd_clean_text(sample_mpp_osd_info mpp_osd_info); + +#ifdef __cplusplus +} +#endif + +#endif // SAMPLE_COMMON_SVP_OSD_H \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/data/hzk/hzk16 b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/data/hzk/hzk16 new file mode 100755 index 0000000000000000000000000000000000000000..460e0550372c3317fe0b901b14e84ce65ddc9e50 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/data/hzk/hzk16 differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/data/model/fruit_identify.om b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/data/model/fruit_identify.om new file mode 100755 index 0000000000000000000000000000000000000000..c8bda4529527724097744a302b5c311f530ccdb2 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/data/model/fruit_identify.om differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/apple/audio_chn0.aac b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/apple/audio_chn0.aac new file mode 100755 index 0000000000000000000000000000000000000000..be17a8c4b7dc63b33b3ec46196db5cedb1ab7a25 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/apple/audio_chn0.aac differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/banana/audio_chn0.aac b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/banana/audio_chn0.aac new file mode 100755 index 0000000000000000000000000000000000000000..f7f529304bd73f4de175ba167ae501075c852b00 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/banana/audio_chn0.aac differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/orange/audio_chn0.aac b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/orange/audio_chn0.aac new file mode 100755 index 0000000000000000000000000000000000000000..41d79b4688bcaba26971ff36e7bbd3bf42f47fbc Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/orange/audio_chn0.aac differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/pear/audio_chn0.aac b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/pear/audio_chn0.aac new file mode 100755 index 0000000000000000000000000000000000000000..cf40ce599eda4aaad8d6bc75465fd1117cd0d8ac Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/pear/audio_chn0.aac differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/watermelon/audio_chn0.aac b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/watermelon/audio_chn0.aac new file mode 100755 index 0000000000000000000000000000000000000000..7a13293d952ff025530b18bb49670a522013da11 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_audio/watermelon/audio_chn0.aac differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_identify.c b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_identify.c new file mode 100755 index 0000000000000000000000000000000000000000..db0faaed36d1dae9735ce4b38dbf040c4c7d7308 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/fruit_identify.c @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +/* 新增v4l2相关头文件 */ +#include // 文件控制 +#include // 错误处理 +#include // POSIX API +#include // 字符串操作 +#include // 内存映射 +#include // IO控制 +#include // select复用 +#include // v4l2核心 + +#include "svp_acl_rt.h" +#include "svp_acl.h" +#include "svp_acl_ext.h" +#include "sample_audio.h" // 包含音频文件 +#include "audio_aac_adp.h" +#include "sdk_module_init.h" +#include "common/sample_common_svp_osd.h" // osd头文件 +#include "common/sample_common_svp.h" +#include "common/sample_common_svp_npu.h" +#include "common/sample_common_svp_npu_model.h" + +#define SAMPLE_SVP_NPU_SHAERD_WORK_BUF_NUM 1 +#define SAMPLE_SVP_NPU_YOLO_TYPE_NUM 12 +#define SAMPLE_SVP_NPU_YOLO_THRESHOLD_NUM 1 +#define SAMPLE_SVP_NPU_PATH_LEN 0x100 + +static int g_last_played_class_id = -1; +static td_bool g_svp_npu_terminate_signal = TD_FALSE; +static td_s32 g_svp_npu_dev_id = 0; +static sample_svp_npu_task_info g_svp_npu_task[SAMPLE_SVP_NPU_MAX_TASK_NUM] = {0}; +static sample_svp_npu_shared_work_buf g_svp_npu_shared_work_buf[SAMPLE_SVP_NPU_SHAERD_WORK_BUF_NUM] = {0}; + +static sample_svp_npu_threshold g_svp_npu_rfcn_threshold[SAMPLE_SVP_NPU_RFCN_THRESHOLD_NUM] = { + {0.7, 0.0, 16.0, 16.0, "rpn_data"}, {0.3, 0.9, 16.0, 16.0, "rpn_data1"} +}; + +static sample_svp_npu_threshold g_svp_npu_yolo_threshold[SAMPLE_SVP_NPU_YOLO_TYPE_NUM] = { + {0.9, 0.15, 1.0, 1.0, "rpn_data"}, // yolov8 +}; + +static sample_svp_npu_roi_info g_svp_npu_yolo_roi_info[SAMPLE_SVP_NPU_YOLO_TYPE_NUM] = { + {"output0", "output0_"}, // yolov8 +}; + +static sample_vi_cfg g_vi_config; +static ot_sample_svp_rect_info g_svp_npu_rect_info = {0}; +static td_bool g_svp_npu_thread_stop = TD_FALSE; +static pthread_t g_svp_npu_thread = 0; +static sample_vo_cfg g_svp_npu_vo_cfg = { 0 }; +static pthread_t g_svp_npu_vdec_thread = 0; +static ot_vb_pool_info g_svp_npu_vb_pool_info; +static td_void *g_svp_npu_vb_virt_addr = TD_NULL; + +static ot_sample_svp_media_cfg g_svp_npu_media_cfg = { + .svp_switch = {TD_FALSE, TD_TRUE}, + .pic_type = {PIC_1080P, PIC_CIF}, + .chn_num = OT_SVP_MAX_VPSS_CHN_NUM, +}; + +static sample_vdec_attr g_svp_npu_vdec_cfg = { + .type = OT_PT_MJPEG, + .mode = OT_VDEC_SEND_MODE_FRAME, + .width = FHD_WIDTH, + .height = FHD_HEIGHT, + .sample_vdec_picture.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420, /* 420:pixel_format */ + .sample_vdec_picture.alpha = 0, /* 0:alpha */ + .display_frame_num = 2, /* 2:display_frame_num */ + .frame_buf_cnt = 5, /* 5:2+2+1 */ +}; + +static vdec_thread_param g_svp_npu_vdec_param = { + .chn_id = 0, + + .v4l2_device = "/dev/video0", // 摄像头设备 + .width = FHD_WIDTH, // 采集分辨率宽 + .height = FHD_HEIGHT, // 采集分辨率高 + .pixel_format = V4L2_PIX_FMT_MJPEG, // MJPEG格式 + + .type = OT_PT_MJPEG, + .stream_mode = OT_VDEC_SEND_MODE_FRAME, + .interval_time = 1000, /* 1000:interval_time */ + .pts_init = 0, + .pts_increase = 0, + .e_thread_ctrl = THREAD_CTRL_START, + .circle_send = TD_TRUE, + .milli_sec = 0, + .min_buf_size = (FHD_WIDTH * FHD_HEIGHT * 3) >> 1, /* 3:chn_size */ + .fps = 30, +}; + +// 音频线程 +typedef struct { + int class_id; +} audio_play_param; + +void* audio_play_thread(void* arg) +{ + audio_play_param* param = (audio_play_param*)arg; + td_s32 audio_ret = TD_SUCCESS; + + switch (param->class_id) { + case 0: + audio_ret = sample_audio_adec_ao("fruit_audio", "pear"); + break; + case 1: + audio_ret = sample_audio_adec_ao("fruit_audio", "watermelon"); + break; + case 2: /* 2: case of orange */ + audio_ret = sample_audio_adec_ao("fruit_audio", "orange"); + break; + case 3: /* 3: case of banana */ + audio_ret = sample_audio_adec_ao("fruit_audio", "banana"); + break; + case 4: /* 4: case of apple */ + audio_ret = sample_audio_adec_ao("fruit_audio", "apple"); + break; + default: + audio_ret = TD_SUCCESS; + break; + } + + if (audio_ret != TD_SUCCESS) { + sample_svp_trace_err("play audio failed!\n"); + } else { + sample_svp_trace_info("play audio success!\n"); + } + + free(param); // 释放参数 + return NULL; +} + +static td_void sample_svp_npu_acl_terminate(td_void) +{ + if (g_svp_npu_terminate_signal == TD_TRUE) { + printf("\033[0;31mprogram termination abnormally!\033[0;39m\n"); + } +} + +/* function : svp npu signal handle */ +td_void sample_svp_npu_acl_handle_sig(td_void) +{ + g_svp_npu_terminate_signal = TD_TRUE; +} + +static td_void sample_svp_npu_acl_deinit(td_void) +{ + svp_acl_error ret; + + ret = svp_acl_rt_reset_device(g_svp_npu_dev_id); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("reset device fail\n"); + } + sample_svp_trace_info("end to reset device is %d\n", g_svp_npu_dev_id); + + ret = svp_acl_finalize(); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("finalize acl fail\n"); + } + sample_svp_trace_info("end to finalize acl\n"); + (td_void)sample_common_svp_check_sys_exit(); +} + +static td_s32 sample_svp_npu_acl_init(const td_char *acl_config_path, td_bool vi_en) +{ + /* svp acl init */ + svp_acl_rt_run_mode run_mode; + svp_acl_error ret; + td_bool is_mpi_init; + + is_mpi_init = sample_common_svp_check_sys_init(vi_en); + sample_svp_check_exps_return(is_mpi_init != TD_TRUE, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "mpi init failed!\n"); + + ret = svp_acl_init(acl_config_path); + sample_svp_check_exps_return(ret != SVP_ACL_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "acl init failed!\n"); + + sample_svp_trace_info("svp acl init success!\n"); + + /* open device */ + ret = svp_acl_rt_set_device(g_svp_npu_dev_id); + if (ret != SVP_ACL_SUCCESS) { + (td_void)svp_acl_finalize(); + sample_svp_trace_err("svp acl open device %d failed!\n", g_svp_npu_dev_id); + return TD_FAILURE; + } + sample_svp_trace_info("open device %d success!\n", g_svp_npu_dev_id); + + /* get run mode */ + ret = svp_acl_rt_get_run_mode(&run_mode); + if ((ret != SVP_ACL_SUCCESS) || (run_mode != SVP_ACL_DEVICE)) { + (td_void)svp_acl_rt_reset_device(g_svp_npu_dev_id); + (td_void)svp_acl_finalize(); + sample_svp_trace_err("acl get run mode failed!\n"); + return TD_FAILURE; + } + sample_svp_trace_info("get run mode success!\n"); + + return TD_SUCCESS; +} + +static td_s32 sample_svp_npu_acl_dataset_init(td_u32 task_idx) +{ + td_s32 ret = sample_common_svp_npu_create_input(&g_svp_npu_task[task_idx]); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "create input failed!\n"); + + ret = sample_common_svp_npu_create_output(&g_svp_npu_task[task_idx]); + if (ret != TD_SUCCESS) { + sample_common_svp_npu_destroy_input(&g_svp_npu_task[task_idx]); + sample_svp_trace_err("execute create output fail.\n"); + return TD_FAILURE; + } + return TD_SUCCESS; +} + +static td_void sample_svp_npu_acl_dataset_deinit(td_u32 task_idx) +{ + (td_void)sample_common_svp_npu_destroy_input(&g_svp_npu_task[task_idx]); + (td_void)sample_common_svp_npu_destroy_output(&g_svp_npu_task[task_idx]); +} + +static td_void *sample_svp_npu_acl_thread_execute(td_void *args) +{ + td_s32 ret; + td_u32 task_idx = *(td_u32 *)args; + + ret = svp_acl_rt_set_device(g_svp_npu_dev_id); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, + "open device %d failed!\n", g_svp_npu_dev_id); + + ret = sample_common_svp_npu_model_execute(&g_svp_npu_task[task_idx]); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("execute inference failed of task[%u]!\n", task_idx); + } + + ret = svp_acl_rt_reset_device(g_svp_npu_dev_id); + if (ret != SVP_ACL_SUCCESS) { + sample_svp_trace_err("task[%u] reset device failed!\n", task_idx); + } + return TD_NULL; +} + +static td_void sample_svp_npu_acl_model_execute_multithread() +{ + pthread_t execute_threads[SAMPLE_SVP_NPU_MAX_THREAD_NUM] = {0}; + td_u32 idx[SAMPLE_SVP_NPU_MAX_THREAD_NUM] = {0}; + td_u32 task_idx; + + for (task_idx = 0; task_idx < SAMPLE_SVP_NPU_MAX_THREAD_NUM; task_idx++) { + idx[task_idx] = task_idx; + pthread_create(&execute_threads[task_idx], NULL, sample_svp_npu_acl_thread_execute, &idx[task_idx]); + } + + td_void *waitret[SAMPLE_SVP_NPU_MAX_THREAD_NUM]; + for (task_idx = 0; task_idx < SAMPLE_SVP_NPU_MAX_THREAD_NUM; task_idx++) { + pthread_join(execute_threads[task_idx], &waitret[task_idx]); + } + + for (task_idx = 0; task_idx < SAMPLE_SVP_NPU_MAX_THREAD_NUM; task_idx++) { + sample_svp_trace_info("output %u-th task data\n", task_idx); + sample_common_svp_npu_output_classification_result(&g_svp_npu_task[task_idx]); + } +} + +static td_void sample_svp_npu_acl_deinit_task(td_u32 task_num, td_u32 shared_work_buf_idx) +{ + td_u32 task_idx; + + for (task_idx = 0; task_idx < task_num; task_idx++) { + (td_void)sample_common_svp_npu_destroy_work_buf(&g_svp_npu_task[task_idx]); + (td_void)sample_common_svp_npu_destroy_task_buf(&g_svp_npu_task[task_idx]); + (td_void)sample_svp_npu_acl_dataset_deinit(task_idx); + (td_void)memset_s(&g_svp_npu_task[task_idx], sizeof(sample_svp_npu_task_cfg), 0, + sizeof(sample_svp_npu_task_cfg)); + } + if (g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr != TD_NULL) { + (td_void)svp_acl_rt_free(g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr); + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr = TD_NULL; + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size = 0; + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_stride = 0; + } +} + +static td_s32 sample_svp_npu_acl_create_shared_work_buf(td_u32 task_num, td_u32 shared_work_buf_idx) +{ + td_u32 task_idx; + td_u32 work_buf_size; + td_u32 work_buf_stride; + td_s32 ret; + + for (task_idx = 0; task_idx < task_num; task_idx++) { + ret = sample_common_svp_npu_get_work_buf_info(&g_svp_npu_task[task_idx], &work_buf_size, &work_buf_stride); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get %u-th task work buf info failed!\n", task_idx); + + if (g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size < work_buf_size) { + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size = work_buf_size; + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_stride = work_buf_stride; + } + } + ret = svp_acl_rt_malloc_cached(&g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr, + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size, SVP_ACL_MEM_MALLOC_NORMAL_ONLY); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "malloc %u-th shared work buf failed!\n", shared_work_buf_idx); + + (td_void)svp_acl_rt_mem_flush(g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_ptr, + g_svp_npu_shared_work_buf[shared_work_buf_idx].work_buf_size); + return TD_SUCCESS; +} + +static td_s32 sample_svp_npu_acl_init_task(td_u32 task_num, td_bool is_share_work_buf, + td_u32 shared_work_buf_idx) +{ + td_u32 task_idx; + td_s32 ret; + + if (is_share_work_buf == TD_TRUE) { + ret = sample_svp_npu_acl_create_shared_work_buf(task_num, shared_work_buf_idx); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "create shared work buf failed!\n"); + } + + for (task_idx = 0; task_idx < task_num; task_idx++) { + ret = sample_svp_npu_acl_dataset_init(task_idx); + if (ret != TD_SUCCESS) { + goto task_init_end_0; + } + ret = sample_common_svp_npu_create_task_buf(&g_svp_npu_task[task_idx]); + if (ret != TD_SUCCESS) { + sample_svp_trace_err("create task buf failed.\n"); + goto task_init_end_0; + } + if (is_share_work_buf == TD_FALSE) { + ret = sample_common_svp_npu_create_work_buf(&g_svp_npu_task[task_idx]); + } else { + /* if all tasks are on the same stream, work buf can be shared */ + ret = sample_common_svp_npu_share_work_buf(&g_svp_npu_shared_work_buf[shared_work_buf_idx], + &g_svp_npu_task[task_idx]); + } + if (ret != TD_SUCCESS) { + sample_svp_trace_err("create work buf failed.\n"); + goto task_init_end_0; + } + } + return TD_SUCCESS; + +task_init_end_0: + (td_void)sample_svp_npu_acl_deinit_task(task_num, shared_work_buf_idx); + return ret; +} + +// 辅助函数:根据class_id播放音频(如果类别发生变化) +static void play_audio_if_class_changed(void) +{ + int max_idx = -1; + double max_score = 0.5; + + // 检测到目标时,启动音频播放线程 + for (int i = 0; i < g_svp_npu_rect_info.num; i++) { + if (g_svp_npu_rect_info.rect[i].score >= max_score) { + if (max_idx == -1 || g_svp_npu_rect_info.rect[i].score > g_svp_npu_rect_info.rect[max_idx].score) { + max_idx = i; + } + } + } + // ...existing code... + if (max_idx != -1) { + int current_class_id = g_svp_npu_rect_info.rect[max_idx].class_id; + if (current_class_id != g_last_played_class_id) { + pthread_t audio_thread; + audio_play_param* param = malloc(sizeof(audio_play_param)); + if (param != NULL) { + param->class_id = current_class_id; + pthread_create(&audio_thread, NULL, audio_play_thread, param); + pthread_detach(audio_thread); // 不阻塞主流程 + g_last_played_class_id = current_class_id; // 只在播放时更新 + } + } + } +} + +static void get_detection_results(void) +{ + // 循环打印置信度和类别ID + for (int i = 0; i < g_svp_npu_rect_info.num; i++) { + const char* class_name = NULL; + switch (g_svp_npu_rect_info.rect[i].class_id) { + case 0: + class_name = "梨子"; + break; + case 1: + class_name = "西瓜"; + break; + case 2: /* 2: case of orange */ + class_name = "橘子"; + break; + case 3: /* 3: case of banana */ + class_name = "香蕉"; + break; + case 4: /* 4: case of apple */ + class_name = "苹果"; + break; + default: + class_name = "未知"; + break; + } + printf("score:%lf, class_id:%d, name:%s\r\n", + g_svp_npu_rect_info.rect[i].score, + g_svp_npu_rect_info.rect[i].class_id, + class_name); + } +} + +static td_s32 sample_svp_npu_acl_frame_proc(const ot_video_frame_info *ext_frame, + const ot_video_frame_info *base_frame, td_void *args) +{ + td_s32 ret; + td_void *virt_addr = TD_NULL; + sample_svp_npu_detection_info *detection_info = TD_NULL; + sample_svp_npu_thread_args *thread_args = (sample_svp_npu_thread_args *)args; + td_u32 size = (td_u32)(ext_frame->video_frame.height * ext_frame->video_frame.stride[0] * + SAMPLE_SVP_NPU_IMG_THREE_CHN / SAMPLE_SVP_NPU_DOUBLE); + + virt_addr = g_svp_npu_vb_virt_addr + + (ext_frame->video_frame.phys_addr[0] - g_svp_npu_vb_pool_info.pool_phy_addr); + ret = sample_common_svp_npu_update_input_data_buffer_info(virt_addr, size, + ext_frame->video_frame.stride[0], 0, &g_svp_npu_task[0]); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "update data buffer failed!\n"); + + ret = sample_common_svp_npu_model_execute(&g_svp_npu_task[0]); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "model execute failed!\n"); + + play_audio_if_class_changed(); + + // ...existing code... + if (thread_args->model_name == SAMPLE_SVP_NPU_RFCN || thread_args->model_name == SAMPLE_SVP_NPU_YOLO) { + detection_info = thread_args->detection_info; + if (detection_info->is_cpu_rpn == TD_FALSE) { + ret = sample_common_svp_npu_roi_to_rect(&g_svp_npu_task[0], detection_info, ext_frame, base_frame, + &g_svp_npu_rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "roi to rect failed!\n"); + } else { + ret = sample_common_svp_npu_roi_to_rect_cpu(&g_svp_npu_task[0], detection_info, ext_frame, base_frame, + &g_svp_npu_rect_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "roi to rect failed!\n"); + } + ret = sample_common_svp_vgs_fill_rect(base_frame, &g_svp_npu_rect_info, SAMPLE_SVP_NPU_RECT_COLOR); + sample_svp_check_exps_return(ret != TD_SUCCESS, ret, SAMPLE_SVP_ERR_LEVEL_ERROR, "vgs fill rect failed!\n"); + + // 在屏幕上打印信息检测到的水果信息 + int i; + for (i = 0; i < (g_svp_npu_rect_info.num); i++) { + sample_osd_draw_text(g_svp_npu_rect_info.rect[i].score, g_svp_npu_rect_info.rect[i].class_id, + g_svp_npu_rect_info.rect[i].point[0].x, g_svp_npu_rect_info.rect[i].point[0].y, + thread_args->mpp_osd_info); + } + if (g_svp_npu_rect_info.num == 0) { + thread_args->mpp_osd_info.chn_attr.is_show = TD_FALSE; + sample_osd_clean_text(thread_args->mpp_osd_info); + } + } + get_detection_results(); + + return ret; +} + +static td_s32 sample_svp_npu_acl_vb_map(td_u32 vb_pool_idx) +{ + td_s32 ret; + + if (g_svp_npu_vb_virt_addr == TD_NULL) { + ret = ss_mpi_vb_get_pool_info(g_svp_npu_media_cfg.vb_pool[vb_pool_idx], &g_svp_npu_vb_pool_info); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "get pool info failed!\n"); + g_svp_npu_vb_virt_addr = ss_mpi_sys_mmap(g_svp_npu_vb_pool_info.pool_phy_addr, + g_svp_npu_vb_pool_info.pool_size); + sample_svp_check_exps_return(g_svp_npu_vb_virt_addr == TD_NULL, TD_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "map vb pool failed!\n"); + } + return TD_SUCCESS; +} + +static td_void *sample_svp_npu_acl_vdec_to_vo(td_void *args) +{ + td_s32 ret; + ot_video_frame_info base_frame; + ot_video_frame_info ext_frame; + const td_s32 milli_sec = SAMPLE_SVP_NPU_MILLIC_SEC; + const ot_vo_layer vo_layer = 0; + const ot_vo_chn vo_chn = 0; + const td_s32 vpss_grp = 0; + td_s32 vpss_chn[] = { OT_VPSS_CHN0, OT_VPSS_CHN1 }; + td_u32 size; + td_u32 stride; + td_u8 *data = TD_NULL; + + (td_void)prctl(PR_SET_NAME, "svp_npu_vdec_to_vo", 0, 0, 0); + + ret = svp_acl_rt_set_device(g_svp_npu_dev_id); + sample_svp_check_exps_return(ret != TD_SUCCESS, TD_NULL, SAMPLE_SVP_ERR_LEVEL_ERROR, "open device failed!\n"); + + ret = sample_svp_npu_acl_vb_map(OT_VPSS_CHN1); + sample_svp_check_exps_goto(ret != TD_SUCCESS, fail_0, SAMPLE_SVP_ERR_LEVEL_ERROR, "map vb pool failed!\n"); + + ret = sample_common_svp_npu_get_input_data_buffer_info(&g_svp_npu_task[0], 0, &data, &size, &stride); + sample_svp_check_exps_goto(ret != TD_SUCCESS, fail_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),get_input_data_buffer_info failed!\n", ret); + + while (g_svp_npu_thread_stop == TD_FALSE) { + ret = ss_mpi_vpss_get_chn_frame(vpss_grp, vpss_chn[1], &ext_frame, milli_sec); + sample_svp_check_exps_continue(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),ss_mpi_vpss_get_chn_frame failed, vpss_grp(%d), vpss_chn(%d)!\n", ret, vpss_grp, vpss_chn[1]); + + ret = ss_mpi_vpss_get_chn_frame(vpss_grp, vpss_chn[0], &base_frame, milli_sec); + sample_svp_check_exps_goto(ret != TD_SUCCESS, ext_release, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),ss_mpi_vpss_get_chn_frame failed, VPSS_GRP(%d), VPSS_CHN(%d)!\n", ret, vpss_grp, vpss_chn[0]); + + ret = sample_svp_npu_acl_frame_proc(&ext_frame, &base_frame, args); + sample_svp_check_exps_goto(ret != TD_SUCCESS, base_release, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_svp_npu_acl_frame_proc failed!\n", ret); + + ret = sample_common_svp_venc_vo_send_stream(&g_svp_npu_media_cfg.svp_switch, 0, vo_layer, vo_chn, &base_frame); + sample_svp_check_exps_goto(ret != TD_SUCCESS, base_release, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),sample_common_svp_venc_vo_send_stream failed!\n", ret); +base_release: + ret = ss_mpi_vpss_release_chn_frame(vpss_grp, vpss_chn[0], &base_frame); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),release_frame failed,grp(%d) chn(%d)!\n", ret, vpss_grp, vpss_chn[0]); +ext_release: + ret = ss_mpi_vpss_release_chn_frame(vpss_grp, vpss_chn[1], &ext_frame); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),release_frame failed,grp(%d) chn(%d)!\n", ret, vpss_grp, vpss_chn[1]); + } + ret = sample_common_svp_npu_update_input_data_buffer_info(data, size, stride, 0, &g_svp_npu_task[0]); + sample_svp_check_exps_trace(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, "update buffer failed!\n"); +fail_1: + (td_void)ss_mpi_sys_munmap(g_svp_npu_vb_virt_addr, g_svp_npu_vb_pool_info.pool_size); +fail_0: + (td_void)svp_acl_rt_reset_device(g_svp_npu_dev_id); + return TD_NULL; +} + +static td_void sample_svp_npu_acl_pause(td_void) +{ + printf("---------------press Enter key to exit!---------------\n"); + if (g_svp_npu_terminate_signal == TD_TRUE) { + return; + } + (td_void)getchar(); + if (g_svp_npu_terminate_signal == TD_TRUE) { + return; + } +} + +static td_void sample_svp_npu_acl_set_task_info(td_u32 model_idx) +{ + g_svp_npu_task[0].cfg.max_batch_num = 1; + g_svp_npu_task[0].cfg.dynamic_batch_num = 1; + g_svp_npu_task[0].cfg.total_t = 0; + g_svp_npu_task[0].cfg.is_cached = TD_TRUE; + g_svp_npu_task[0].cfg.model_idx = model_idx; +} + +static td_void sample_svp_npu_acl_set_detection_info(sample_svp_npu_detection_info *detection_info, td_u32 index, + td_bool is_cpu_rpn) +{ + detection_info->num_name = g_svp_npu_yolo_roi_info[index].roi_num_name; + detection_info->roi_name = g_svp_npu_yolo_roi_info[index].roi_class_name; + detection_info->has_background = TD_FALSE; + detection_info->is_cpu_rpn = is_cpu_rpn; + detection_info->idx = index; + /* use PIC_BUTT to be a flag, get the input resolution form om */ + g_svp_npu_media_cfg.pic_type[1] = PIC_BUTT; + g_svp_npu_terminate_signal = TD_FALSE; +} + +static void sample_svp_audio_init() +{ + // 初始化音频编解码器 + ss_mpi_aenc_aac_init(); + ss_mpi_adec_aac_init(); +} + +static void sample_svp_audio_exit() +{ + // 反初始化音频 + ss_mpi_aenc_aac_deinit(); + ss_mpi_adec_aac_deinit(); +} + +/* 处理线程管理模块 */ +static td_s32 start_processing_thread(sample_svp_npu_thread_args *args) +{ + td_s32 ret; + + ret = sample_common_svp_npu_set_threshold(&g_svp_npu_yolo_threshold[0], + SAMPLE_SVP_NPU_YOLO_THRESHOLD_NUM, &g_svp_npu_task[0]); + + sample_svp_audio_init(); + g_svp_npu_thread_stop = TD_FALSE; + + ret = pthread_create(&g_svp_npu_thread, 0, sample_svp_npu_acl_vdec_to_vo, (td_void*)args); + + return TD_SUCCESS; +} + +/* function : show the sample of yolo. RPN processed by npu */ +td_void sample_svp_npu_acl_yolo_npu(void) +{ + td_s32 ret; + ot_mpp_chn chn; + td_s32 handle; + const td_u32 model_idx = 0; + const td_char *om_model_path = "./data/model/fruit_identify.om"; + sample_svp_npu_detection_info detection_info = {0}; + sample_svp_npu_thread_args args = {SAMPLE_SVP_NPU_YOLO, &detection_info}; + + sample_svp_npu_acl_set_detection_info(&detection_info, 0, TD_FALSE); + + if (g_svp_npu_terminate_signal == TD_FALSE) { + /* init acl */ + ret = sample_svp_npu_acl_init(TD_NULL, TD_FALSE); + sample_svp_check_exps_return_void(ret != TD_SUCCESS, SAMPLE_SVP_ERR_LEVEL_ERROR, "init failed!\n"); + + /* load model */ + ret = sample_common_svp_npu_load_model(om_model_path, model_idx, TD_FALSE); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "load model failed!\n"); + + /* get input resolution */ + ret = sample_common_svp_npu_get_input_resolution(model_idx, 0, &g_svp_npu_media_cfg.pic_size[1]); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "load model failed!\n"); + + /* start vdec vpss venc vo */ + ret = sample_common_svp_create_vb_start_vdec_vpss_vo(&g_svp_npu_vdec_cfg, &g_svp_npu_vdec_param, + &g_svp_npu_vdec_thread, &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end1, SAMPLE_SVP_ERR_LEVEL_DEBUG, + "init media failed!\n"); + + // osd init + sample_osd_init(&args.mpp_osd_info); + + /* set cfg */ + sample_svp_npu_acl_set_task_info(model_idx); + + ret = sample_svp_npu_acl_init_task(1, TD_FALSE, 0); + sample_svp_check_exps_goto(ret != TD_SUCCESS, process_end2, SAMPLE_SVP_ERR_LEVEL_ERROR, "init task failed!\n"); + } + /* process */ + if (g_svp_npu_terminate_signal == TD_FALSE) { + // 处理线程启动 + ret = start_processing_thread(&args); + sample_svp_check_exps_goto(ret != 0, process_end3, SAMPLE_SVP_ERR_LEVEL_ERROR, "create thread failed!\n"); + + (td_void)sample_svp_npu_acl_pause(); + + g_svp_npu_thread_stop = TD_TRUE; + pthread_join(g_svp_npu_thread, TD_NULL); + } + +process_end3: + (td_void)sample_svp_npu_acl_deinit_task(1, 0); +process_end2: + sample_osd_exit(&args.mpp_osd_info); + (td_void)sample_common_svp_destroy_vb_stop_vdec_vpss_vo(&g_svp_npu_vdec_param, &g_svp_npu_vdec_thread, + &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); +process_end1: + (td_void)sample_common_svp_npu_unload_model(model_idx); +process_end0: + (td_void)sample_svp_npu_acl_deinit(); + (td_void)sample_svp_npu_acl_terminate(); + sample_svp_audio_exit(); +} + +int main(void) +{ +#ifdef CONFIG_USER_SPACE + SDK_init(); +#endif + sample_svp_npu_acl_yolo_npu(); +#ifdef CONFIG_USER_SPACE + SDK_exit(); +#endif + + return 0; +} \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20221114150205685.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20221114150205685.png new file mode 100755 index 0000000000000000000000000000000000000000..4dc4215c962c57ba0e31548fb98c29c789f149d9 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20221114150205685.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250210161601541.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250210161601541.png new file mode 100755 index 0000000000000000000000000000000000000000..80845ece8131933a4cd56ae3bd6119c38e0abd26 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250210161601541.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250210170027454.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250210170027454.png new file mode 100755 index 0000000000000000000000000000000000000000..c06081fc2c963af4d1fa8af506804beedefe1b0b Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250210170027454.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250213112932380.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250213112932380.png new file mode 100755 index 0000000000000000000000000000000000000000..8b591b3437544859f4ec76b9ca03867cc401078c Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250213112932380.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919150630870.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919150630870.png new file mode 100755 index 0000000000000000000000000000000000000000..91f881e85b3292118336ce2c3d81968e4aee8c26 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919150630870.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919151018659.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919151018659.png new file mode 100755 index 0000000000000000000000000000000000000000..9b09507893b65d2142be49e6461daa31a81855c4 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919151018659.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919151519310.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919151519310.png new file mode 100755 index 0000000000000000000000000000000000000000..7f6d881a5d0e6d3f72b7a43d089b5c5a75d7f048 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919151519310.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173612332.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173612332.png new file mode 100755 index 0000000000000000000000000000000000000000..d6b77aee440df447f0a4abcade34334be11c9580 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173612332.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173833285.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173833285.png new file mode 100755 index 0000000000000000000000000000000000000000..0bf4e22357955f8390868050e0f3b4b8ad97376a Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173833285.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173911326.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173911326.png new file mode 100755 index 0000000000000000000000000000000000000000..93af51cb4cfcbc2adfb866c035b592efee9354d0 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919173911326.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919174107506.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919174107506.png new file mode 100755 index 0000000000000000000000000000000000000000..912fdccc2333688a45f928e9fd267f11284fa6a3 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919174107506.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919174301632.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919174301632.png new file mode 100755 index 0000000000000000000000000000000000000000..2fe2ad3ac92f9cce99d64199c81d4383514b5e1f Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919174301632.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175651286.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175651286.png new file mode 100755 index 0000000000000000000000000000000000000000..787594f96e048545d9ffc2e872993994c04f1042 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175651286.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175810259.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175810259.png new file mode 100755 index 0000000000000000000000000000000000000000..e6dbb6ee26c07a5a97528a7726027cdc471c5961 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175810259.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175946122.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175946122.png new file mode 100755 index 0000000000000000000000000000000000000000..89d008483b60abd625c51183c61196c97a79b363 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919175946122.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919180706355.png b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919180706355.png new file mode 100755 index 0000000000000000000000000000000000000000..ba4971e35c5cdaaf64386cebfa6a896383e61c7d Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/pic/image-20250919180706355.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/sample_audio.c b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/sample_audio.c new file mode 100755 index 0000000000000000000000000000000000000000..22d334818f0b025fb71e80c4ec8196f06ea0bc8e --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/sample_audio.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sample_comm.h" +#include "audio_aac_adp.h" +#include "audio_dl_adp.h" +#include "ot_resample.h" + +#include "sample_audio.h" + +static ot_payload_type g_payload_type = OT_PT_AAC; +static td_bool g_aio_resample = TD_FALSE; +static ot_audio_sample_rate g_in_sample_rate = OT_AUDIO_SAMPLE_RATE_BUTT; +static ot_audio_sample_rate g_out_sample_rate = OT_AUDIO_SAMPLE_RATE_BUTT; + +#define sample_dbg(ret) \ + do { \ + printf("ret = %#x, fuc:%s, line:%d\n", ret, __FUNCTION__, __LINE__); \ + } while (0) + +#define sample_res_check_null_ptr(ptr) \ + do { \ + if ((td_u8*)(ptr) == TD_NULL) { \ + printf("ptr is TD_NULL,fuc:%s,line:%d\n", __FUNCTION__, __LINE__); \ + return TD_FAILURE; \ + } \ + } while (0) + +/* function : PT number to string */ +static char *sample_audio_pt2_str(ot_payload_type type) +{ + if (type == OT_PT_G711A) { + return "g711a"; + } else if (type == OT_PT_G711U) { + return "g711u"; + } else if (type == OT_PT_ADPCMA) { + return "adpcm"; + } else if (type == OT_PT_G726) { + return "g726"; + } else if (type == OT_PT_LPCM) { + return "pcm"; + } else if (type == OT_PT_AAC) { + return "aac"; + } else { + return "data"; + } +} + +/* function : open adec file */ +static FILE *sample_audio_open_adec_file(ot_adec_chn ad_chn, ot_payload_type type, + const td_char *file_name1, const td_char *file_name2) +{ + FILE *fd = TD_NULL; + td_char asz_file_name[FILE_NAME_LEN] = {0}; + td_s32 ret; + td_char path[PATH_MAX] = {0}; + + /* create file for save stream */ +#ifdef __LITEOS__ + ret = snprintf_s(asz_file_name, FILE_NAME_LEN, FILE_NAME_LEN - 1, + "/sharefs/audio_chn%d.%s", ad_chn, sample_audio_pt2_str(type)); +#else + ret = snprintf_s(asz_file_name, FILE_NAME_LEN, FILE_NAME_LEN - 1, + "%s/%s/audio_chn%d.%s", file_name1, file_name2, ad_chn, sample_audio_pt2_str(type)); +#endif + if (ret < 0) { + printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "get adec file name failed"); + return TD_NULL; + } + + if (asz_file_name[0] == '\0') { + printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "adec file name is NULL"); + return TD_NULL; + } + + if (strlen(asz_file_name) > (FILE_NAME_LEN - 1)) { + printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "adec file name extra long"); + return TD_NULL; + } + + if (realpath(asz_file_name, path) == TD_NULL) { + printf("[func]:%s [line]:%d [info]:%s\n", __FUNCTION__, __LINE__, "adec file name realpath fail"); + return TD_NULL; + } + + fd = fopen(path, "rb"); + if (fd == NULL) { + printf("%s: open file %s failed\n", __FUNCTION__, asz_file_name); + return NULL; + } + printf("open stream file:\"%s\" for adec ok\n", asz_file_name); + return fd; +} + +static td_void sample_audio_adec_ao_init_param(ot_aio_attr *aio_attr, ot_audio_dev *ao_dev) +{ + aio_attr->sample_rate = OT_AUDIO_SAMPLE_RATE_48000; + aio_attr->bit_width = OT_AUDIO_BIT_WIDTH_16; + aio_attr->work_mode = OT_AIO_MODE_I2S_MASTER; + aio_attr->snd_mode = OT_AUDIO_SOUND_MODE_STEREO; + aio_attr->expand_flag = 0; + aio_attr->frame_num = 30; /* 30:frame num */ + if (g_payload_type == OT_PT_AAC) { + aio_attr->point_num_per_frame = AACLC_SAMPLES_PER_FRAME; + } else { + aio_attr->point_num_per_frame = SAMPLE_AUDIO_POINT_NUM_PER_FRAME; + } + aio_attr->chn_cnt = 2; /* 2:chn num */ +#ifdef OT_ACODEC_TYPE_INNER + *ao_dev = SAMPLE_AUDIO_INNER_AO_DEV; + aio_attr->clk_share = 1; + aio_attr->i2s_type = OT_AIO_I2STYPE_INNERCODEC; +#else + *ao_dev = SAMPLE_AUDIO_EXTERN_AO_DEV; + aio_attr->clk_share = 1; + aio_attr->i2s_type = OT_AIO_I2STYPE_EXTERN; +#endif + g_aio_resample = TD_FALSE; + g_in_sample_rate = OT_AUDIO_SAMPLE_RATE_BUTT; + g_out_sample_rate = OT_AUDIO_SAMPLE_RATE_BUTT; +} + +td_void sample_audio_adec_ao_inner(ot_audio_dev ao_dev, ot_ao_chn ao_chn, ot_adec_chn ad_chn, + const td_char *file_name1, const td_char *file_name2) +{ + td_s32 ret; + FILE *fd = NULL; + + ret = sample_comm_audio_ao_bind_adec(ao_dev, ao_chn, ad_chn); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + return; + } + + fd = sample_audio_open_adec_file(ad_chn, g_payload_type, file_name1, file_name2); + if (fd == TD_NULL) { + sample_dbg(TD_FAILURE); + goto adec_ao_err0; + } + + ret = sample_comm_audio_creat_trd_file_adec(ad_chn, fd); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + fclose(fd); + fd = TD_NULL; + goto adec_ao_err0; + } + + printf("bind adec:%d to ao(%d,%d) ok \n", ad_chn, ao_dev, ao_chn); + + sleep(2); /* 2: sleep 2 seconds */ + + ret = sample_comm_audio_destory_trd_file_adec(ad_chn); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + } + +adec_ao_err0: + ret = sample_comm_audio_ao_unbind_adec(ao_dev, ao_chn, ad_chn); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + } + + return; +} + +/* function : file -> adec -> ao */ +td_s32 sample_audio_adec_ao(const td_char *file_name1, const td_char *file_name2) +{ + td_s32 ret; + td_u32 ao_chn_cnt; + td_u32 adec_chn_cnt; + ot_audio_dev ao_dev; + ot_aio_attr aio_attr; + const ot_ao_chn ao_chn = 0; + const ot_adec_chn ad_chn = 0; + + sample_audio_adec_ao_init_param(&aio_attr, &ao_dev); + + adec_chn_cnt = aio_attr.chn_cnt >> ((td_u32)aio_attr.snd_mode); + ret = sample_comm_audio_start_adec(adec_chn_cnt, g_payload_type); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + goto adec_ao_err3; + } + + ao_chn_cnt = aio_attr.chn_cnt; + ret = sample_comm_audio_start_ao(ao_dev, ao_chn_cnt, &aio_attr, g_in_sample_rate, g_aio_resample); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + goto adec_ao_err2; + } + + ret = sample_comm_audio_cfg_acodec(&aio_attr); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + goto adec_ao_err1; + } + + sample_audio_adec_ao_inner(ao_dev, ao_chn, ad_chn, file_name1, file_name2); + +adec_ao_err1: + ret = sample_comm_audio_stop_ao(ao_dev, ao_chn_cnt, g_aio_resample); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + } + +adec_ao_err2: + ret = sample_comm_audio_stop_adec(ad_chn); + if (ret != TD_SUCCESS) { + sample_dbg(ret); + } + +adec_ao_err3: + return ret; +} \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/sample_audio.h b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/sample_audio.h new file mode 100755 index 0000000000000000000000000000000000000000..ebb5b5babcfbd3795ee222442abad02c792fec35 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/fruit_identify/sample_audio.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SAMPLE_AUDIO_ADEC_AO_H__ +#define __SAMPLE_AUDIO_ADEC_AO_H__ + +#include "sample_comm.h" + +td_s32 sample_audio_adec_ao(const td_char *file_name1, const td_char *file_name2); + + +#endif /* __SAMPLE_AUDIO_ADEC_AO_H__ */ \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/mk.param b/vendor/ZhongShanKuangShi_CUST/demo/mk.param new file mode 100755 index 0000000000000000000000000000000000000000..7e3dfab53c4002c11ded8c0362fb0d96785a1188 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/mk.param @@ -0,0 +1,42 @@ +# 各模块makefile均应在前面include此文件 +export ROOT_DIR := /home/openharmony/pegasus +export SDK_ROOT := $(ROOT_DIR)/platform/ss928v100_clang +export CUST_ROOT := $(ROOT_DIR)/vendor/ZhongShanKuangShi_CUST/ +export THIRD_PARTY_DIR := $(ROOT_DIR)/vendor/opensource +export MPP_DIR := $(SDK_ROOT)/smp/a55_linux/mpp +export OUTPUT_DIR := $(CUST_ROOT)/demo/output/ +export OBJS_DIR := $(CUST_ROOT)/demo/obj/ + +# 交叉编译器 +CLANG_PATH := /home/openharmony/pegasus/os/OpenHarmony/ohos/prebuilts/clang/ohos/linux-x86_64/llvm +export SYSROOT_PATH := /home/openharmony/pegasus/os/OpenHarmony/ohos/out/hispark_ss928v100/ipcamera_hispark_ss928v100_linux/sysroot +COMPILER_PATH := $(CLANG_PATH)/bin/ +export CC:=$(COMPILER_PATH)/clang --target=aarch64-linux-ohos -Wno-unused-command-line-argument --sysroot $(SYSROOT_PATH) -isystem $(SYSROOT_PATH)/usr/include +export CXXCPP := $(COMPILER_PATH)/clang++ --target=aarch64-linux-ohos --sysroot=$(CLANG_PATH)/sysroot -nostdinc -isystem $(CLANG_PATH)/include/c++/v1 -isystem $(CLANG_PATH)/lib/clang/15.0.4/include -isystem $(SYSROOT_PATH)/usr/include/aarch64-linux-ohos -D_LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION=2 -D__ARM_NEON=1 -D__ARM_NEON__=1 -mfpu=neon -resource-dir=$(CLANG_PATH)/lib/clang/15.0.4 +CC += -fuse-ld=lld -rtlib=compiler-rt + +# 编译所依赖的库目录 +export SDK_LINUX_OUT_LIB := $(MPP_DIR)/out/lib +export SDK_LINUX_OUT_SVP_NPU_LIB := $(SDK_LINUX_OUT_LIB)/svp_npu + +# 编译所依赖的头文件和源文件目录 +export SDK_LINUX_INCLUDE_DIR := $(MPP_DIR)/out/include +export SDK_SAMPLE_COMMON_DIR := $(MPP_DIR)/sample/common +export SVP_COMMON_DIR := $(MPP_DIR)/sample/svp/common + +# 第三方软件的库和头文件 +export OPENCV_LIB := $(THIRD_PARTY_DIR)/opencv/lib +export OPENCV_INCLUDE := $(THIRD_PARTY_DIR)/opencv/include/opencv4 + +# target输出的存储目录 +export TARGET_ROOT := ./ +export TARGET_DIR := $(TARGET_ROOT)/out/ + +export AUDIO_SAMPLE := $(MPP_DIR)/sample/audio/ +# cust 项目子模块目录 +export FACE_DETECTION_SAMPLE_DIR := $(CUST_ROOT)/demo/face_detection +export FRUIT_IDENTIFY_SAMPLE_DIR := $(CUST_ROOT)/demo/fruit_identify +export HNR_AUTO_SAMPLE_DIR := $(CUST_ROOT)/demo/hnr_auto +export KCF_TRACK_SAMPLE_DIR := $(CUST_ROOT)/demo/sample_kcf_track +export OPENCV_DNN_SAMPLE_DIR := $(CUST_ROOT)/demo/opencv_dnn + diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/Makefile b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..14ead07993fed2e673e88a02d595ed919dc0d5d9 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/Makefile @@ -0,0 +1,54 @@ +# 编译所需的公共文件 +include ../mk.param + +# 编译后生成的可执行文件名 +TARGET := main + +# 编译此工程需要包含的头文件 +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR)/ +CFLAGS += -I$(SDK_SAMPLE_COMMON_DIR)/ +CFLAGS += -Wno-psabi -I$(OPENCV_INCLUDE)/ +CFLAGS += -I$(OPENCV_DNN_SAMPLE_DIR)/ + + +# 编译此工程需要依赖的.c文件 +SMP_SRCS := $(SDK_SAMPLE_COMMON_DIR)/sample_comm_sys.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_ipc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_isp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vi.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vo.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_mipi_tx.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vpss.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/loadbmp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vdec.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_venc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_exit.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_init.c +SMP_SRCS += $(OPENCV_DNN_SAMPLE_DIR)/host_uvc.c +SMP_SRCS += $(OPENCV_DNN_SAMPLE_DIR)/media_vdec.c + +# 编译此工程需要依赖的.cpp文件 +CPP_SRCS += $(OPENCV_DNN_SAMPLE_DIR)/main.cpp + +# 编译此工程需要包含的库和宏 +CFLAGS += -O3 -g -Wall -DSAMPLE_HNR_SUPPORT +CFLAGS += -fstack-protector-strong +MPI_LIBS += -L$(OPENCV_LIB)/ +MPI_LIBS += -lopencv_videoio -lopencv_calib3d -lopencv_dnn -lopencv_core -lopencv_video +MPI_LIBS += -lopencv_flann -lopencv_features2d -lopencv_highgui -lopencv_imgcodecs +MPI_LIBS += -lopencv_imgproc -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching + +# 根据实际的类型设置,可以用set_sensor脚本设置 +SENSOR0_TYPE = -DSENSOR0_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR1_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR2_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR3_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT + +CFLAGS += $(SENSOR0_TYPE) +CFLAGS += $(SENSOR1_TYPE) +CFLAGS += $(SENSOR2_TYPE) +CFLAGS += $(SENSOR3_TYPE) +# 编译工程所需的mk文件 + +include ../sdk_linux.mk + diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/README.md b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/README.md new file mode 100755 index 0000000000000000000000000000000000000000..3318b331348d8dc62397031abb50a14f2d9df294 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/README.md @@ -0,0 +1,134 @@ +## 2.1、opencv_dnn操作指导 + +### 2.1.1、opencv_dnn程序简介 + +* opencv_dnn sample基于SS928V100平台开发,以EulerPi套件为例,opencv_dnn sample是通过USB camera采集到的图片送到人脸检测模型进行推理,将得到的结果通过HDMI,显示在外接显示屏上面。 +* opencv_dnn案例,模型推理是在CPU上实现了,没有调用svp_npu的接口,都是调用opencv的接口来实现。 + +### 2.1.2、目录 + +```shell +pegasus/vendor/cust/demo/opencv_dnn +|── onnx # 模型文件和汉字库 +|── media_vdec.c # 主要是将推理的结果在HDMI外接显示器上显示 +|── media_vdec.h +|── Makefile # 编译脚本 +|── main.cpp # opencv_dnn sample业务代码 +|── host_uvc.c #参考海思SDK的host_uvc代码 +└── host_uvc.h +``` + +![image-20250919181207847](pic/image-20250919181207847.png) + +### 2.1.3、编译 + +* **注意:在编译cust的demo之前,请确保你已经按照[patch介绍中的步骤](../../README.md#4patch介绍)把补丁打入海思SDK的sample目录下了**。 + +* 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 + +* 步骤2:使用Makefile的方式进行单编 + +* 在Ubuntu的命令行终端,分步执行下面的命令,单编 opencv_dnn sample + + ``` + cd pegasus/vendor/cust/demo/opencv_dnn + + make clean && make + ``` + + ![image-20250919181826651](pic/image-20250919181826651.png) + + * 在opencv_dnn目录下,生成一个名为opencv_dnn的 可执行文件,如下图所示: + + ![image-20250919181855261](pic/image-20250919181855261.png) + +### 2.1.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +* 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +image-20221114150205685 + +* 步骤1:将编译后生成的可执行文件、onnx模型文件都拷贝到SD卡中。 + +![image-20250919183401330](pic/image-20250919183401330.png) + +* 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +image-20250210161601541 + +* 在开发板的终端,执行下面的命令进行SD卡的挂载 + * 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +* 挂载成功后,如下图所示: + +![image-20250919183513040](pic/image-20250919183513040.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +* 首先需要自己准备一根网线 +* 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +* 步骤2:将编译后生成的可执行文件、onnx模型文件、opencv库(在pegasus/vendor/opensource/opencv/lib目录下)都拷贝到Windows的nfs共享路径下 + +![image-20250919182525339](pic/image-20250919182525339.png) + +* 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + * 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + + +``` +ifconfig eth0 192.168.100.100 +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20250919182655395](pic/image-20250919182655395.png) + +### 2.1.5、硬件连接 + +* 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image-20250213112932380](pic/image-20250213112932380.png) + +* 将USB 摄像头接在EulerPi开发板的USB接口上。 + +image-20250919150630870 + +### 2.1.6、功能验证 + +* 在开发板的终端执行下面的命令,运行可执行文件 + +```c +# 把opencv的库添加到环境变量中 +export LD_LIBRARY_PATH=/mnt/lib:$LD_LIBRARY_PATH + +cd /mnt + +chmod +x opencv_dnn + +./opencv_dnn /dev/media0 -fMJPEG -s1920x1080 -Ftest.mjpg +``` + +![image-20250919182937455](pic/image-20250919182937455.png) + +* 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +image-20250210170027454 + +* 如果您看到的现象和下图现象不一致,可以确认一下USB涉嫌头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659.png) + +* 正常情况下,我们会在外接显示屏上看到有人脸的区域被框出来,且在框框的左上角显示置信度。 + +![image-20250919183224310](pic/image-20250919183224310.png) + +* Ctrl + C,然后回车即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310.png) \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/host_uvc.c b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/host_uvc.c new file mode 100755 index 0000000000000000000000000000000000000000..603450806508bff1a59a66b8f875a711ca49f965 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/host_uvc.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include "host_uvc.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define array_size(a) (sizeof(a) / sizeof((a)[0])) + +format_info g_pixel_formats[] = { + { "YUYV", V4L2_PIX_FMT_YUYV, 1 }, + { "MJPEG", V4L2_PIX_FMT_MJPEG, 1 }, + { "H264", V4L2_PIX_FMT_H264, 1 }, + { "H265", V4L2_PIX_FMT_H265, 1 }, + { "NV12", V4L2_PIX_FMT_NV12, 1 }, + { "NV21", V4L2_PIX_FMT_NV21, 1 }, +}; + +static struct option g_opts[] = { + {"file", 2, 0, 'F'}, /* 2 is a number */ + {"format", 1, 0, 'f'}, + {"help", 0, 0, 'h'}, + {"size", 1, 0, 's'}, + {0, 0, 0, 0} +}; + +static const format_info *sample_uvc_v4l2_format_by_fourcc(td_u32 fourcc) +{ + td_u32 i; + + for (i = 0; i < array_size(g_pixel_formats); ++i) { + if (g_pixel_formats[i].fourcc == fourcc) { + return &g_pixel_formats[i]; + } + } + return TD_NULL; +} + +static td_void sample_uvc_usage(const td_char *argv0) +{ + printf("sample_uvc_usage: %s device [options]\n", argv0); + printf("supported options:\n"); + printf("-f, --format format set the video format\n"); + printf("-F, --file[=name] write file\n"); + printf("-h, --help show help info\n"); + printf("-s, --size WxH set the frame size (eg. 1920x1080)\n\n"); + printf("inquire USB device format: ./sample_uvc --enum-formats\n\n"); + printf("example of setting USB device format:\n"); + printf(" ./opencv_dnn /dev/media0 -fH264 -s1920x1080 -Ftest.h264\n"); + printf(" ./opencv_dnn /dev/media0 -fH265 -s1920x1080 -Ftest.h265\n"); + printf(" ./opencv_dnn /dev/media0 -fMJPEG -s1920x1080 -Ftest.mjpg\n"); + printf(" ./opencv_dnn /dev/media0 -fYUYV -s1920x1080 -Ftest.yuv\n"); + printf(" ./opencv_dnn /dev/media0 -fNV21 -s640x360 -Ftest.yuv\n\n"); + printf("note: set macro MEDIA_WORK to 0 to write file on disk.\n\n"); +} + +static const format_info *sample_uvc_v4l2_format_by_name(const td_char *name) +{ + td_u32 i; + for (i = 0; i < array_size(g_pixel_formats); ++i) { + if (!strcmp(g_pixel_formats[i].name, name)) { + return &g_pixel_formats[i]; + } + } + return TD_NULL; +} + +static td_void sample_uvc_list_formats(td_void) +{ + td_u32 i; + for (i = 0; i < array_size(g_pixel_formats); i++) { + sample_print("%s (\"%c%c%c%c\", %u planes)\n", g_pixel_formats[i].name, g_pixel_formats[i].fourcc & 0xff, + (g_pixel_formats[i].fourcc >> 8) & 0xff, (g_pixel_formats[i].fourcc >> 16) & 0xff, /* 8,16:shift */ + (g_pixel_formats[i].fourcc >> 24) & 0xff, g_pixel_formats[i].n_planes); /* 24:shift */ + } +} + +static td_s32 sample_uvc_get_opt(td_s32 argc, td_char *argv[], uvc_ctrl_info *ctrl_info) +{ + td_s32 c; + const format_info *info; + td_char *endptr; + + while ((c = getopt_long(argc, argv, "B:c::Cd:f:F::hi:Iln:p::q:r:R::s:t:uw:x:", g_opts, TD_NULL)) != -1) { + switch (c) { + case 'f': + if (!strcmp("help", optarg)) { + sample_uvc_list_formats(); + return TD_FAILURE; + } + ctrl_info->do_set_format = 1; + info = sample_uvc_v4l2_format_by_name(optarg); + if (info == TD_NULL) { + sample_print("Unsupported video format '%s'\n", optarg); + return TD_FAILURE; + } + ctrl_info->pixelformat = info->fourcc; + break; + case 'F': + ctrl_info->do_file = 1; + if (optarg) { + ctrl_info->pattern = optarg; + } + break; + case 'h': + sample_uvc_usage(argv[0]); + return TD_FAILURE; + case 's': + ctrl_info->do_capture = 1; + ctrl_info->do_set_format = 1; + ctrl_info->width = strtol(optarg, &endptr, 10); /* 10:base */ + if (*endptr != 'x' || endptr == optarg) { + sample_print("Invalid size '%s'\n", optarg); + return TD_FAILURE; + } + ctrl_info->height = strtol(endptr + 1, &endptr, 10); /* 10:base */ + if (*endptr != 0) { + sample_print("Invalid size '%s'\n", optarg); + return TD_FAILURE; + } + break; + default: + sample_print("Run %s -h for help.\n", argv[0]); + return TD_FAILURE; + } + } + return TD_SUCCESS; +} + +static td_void sample_uvc_ctrl_info_init(uvc_ctrl_info *ctrl_info) +{ + ctrl_info->pattern = "frame-#.bin"; + ctrl_info->width = 640; /* 640:width */ + ctrl_info->height = 480; /* 480:height */ + ctrl_info->pixelformat = V4L2_PIX_FMT_YUYV; +} + +const td_char *sample_uvc_v4l2_format_name(td_u32 fourcc) +{ + const format_info *format; + static td_char format_name[5]; /* 5: array len */ + td_u32 i; + format = sample_uvc_v4l2_format_by_fourcc(fourcc); + if (format) { + return format->name; + } + + for (i = 0; i < 4; ++i) { /* 4: format */ + format_name[i] = fourcc & 0xff; + fourcc >>= 8; /* 8: shift */ + } + + format_name[4] = '\0'; /* 4: end */ + return format_name; +} + +td_s32 sample_host_uvc(td_s32 argc, td_char *argv[], uvc_ctrl_info *ctrl_info) +{ + int ret; + sample_uvc_ctrl_info_init(ctrl_info); + ret = sample_uvc_get_opt(argc, argv, ctrl_info); + if (ret != TD_SUCCESS) { + return TD_FAILURE; + } + if (optind >= argc) { + sample_uvc_usage(argv[0]); + return TD_FAILURE; + } + return TD_SUCCESS ; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/host_uvc.h b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/host_uvc.h new file mode 100755 index 0000000000000000000000000000000000000000..2260d03101ecb6a09ad12f938aca663b297f8059 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/host_uvc.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __HOST_UVC_H__ +#define __HOST_UVC_H__ + +#include +#include +#include +#include "sample_comm.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef V4L2_PIX_FMT_H265 +#define V4L2_PIX_FMT_H265 v4l2_fourcc('H', '2', '6', '5') /* H.265 aka HEVC */ +#endif + +typedef struct { + const td_char *name; + td_u32 fourcc; + td_char n_planes; +} format_info; + +typedef struct { + const td_char *pattern; + const td_char *type_name; + td_s32 do_capture; + td_s32 do_set_format; + td_u32 pixelformat; + td_s32 do_file; + td_u32 input; + td_u32 width; + td_u32 height; +} uvc_ctrl_info; + +td_s32 sample_host_uvc(td_s32 argc, td_char *argv[], uvc_ctrl_info *ctrl_info); +const td_char *sample_uvc_v4l2_format_name(td_u32 fourcc); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + +#endif /* end of #ifndef __HOST_UVC_H__ */ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/main.cpp b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f7a639decea635484fce719becd28e1b99832511 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/main.cpp @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include +#include +#include "host_uvc.h" +#include "media_vdec.h" +#include "sdk_module_init.h" + +using namespace cv; +using namespace std; +using namespace std::chrono; + +td_bool g_uvc_exit = TD_FALSE; + +// 优化内存管理类 +class MemoryManager { +public: + static void optimizeMemory() + { + cv::setUseOptimized(true); + cv::setNumThreads(4); /* 4: Number of CPU cores */ + } +}; + +static void sample_uvc_exit_signal_handler(int signal) +{ + printf("收到退出信号,准备退出...\n"); + g_uvc_exit = TD_TRUE; +} + +int main(int argc, char** argv) +{ + // 优化内存使用 + MemoryManager::optimizeMemory(); + + int ret; + uvc_ctrl_info ctrl_info = {0}; + struct sigaction sig_exit; + sig_exit.sa_handler = sample_uvc_exit_signal_handler; + sigaction(SIGINT, &sig_exit, nullptr); + sigaction(SIGTERM, &sig_exit, nullptr); + ret = sample_host_uvc(argc, argv, &ctrl_info); + if (ret != TD_SUCCESS) { + return TD_FAILURE; + } +#ifdef CONFIG_USER_SPACE + SDK_init(); +#endif + // OpenCV V4L2 video capture + VideoCapture cap(0, cv::CAP_V4L2); + if (!cap.isOpened()) { + printf("Error: Failed to open camera device!\n"); + return -1; + } + + int width = ctrl_info.width; + int height = ctrl_info.height; + int fps = 30; + + // 设置摄像头参数 + cap.set(CAP_PROP_FRAME_WIDTH, width); + cap.set(CAP_PROP_FRAME_HEIGHT, height); + cap.set(CAP_PROP_FPS, fps); + cap.set(CAP_PROP_BUFFERSIZE, 4); /* 4: Increase buffer size */ + + // 根据格式设置摄像头参数 + const char* type_name = sample_uvc_v4l2_format_name(ctrl_info.pixelformat); + if (strcmp(type_name, "MJPEG") == 0) { + cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G')); + } else if (strcmp(type_name, "YUYV") == 0) { + cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('Y', 'U', 'Y', 'V')); + } else { + std::cerr << "只支持 YUYV 或 MJPEG 格式,请用 -fYUYV 或 -fMJPEG 参数启动!" << std::endl; + return -1; + } + + // 验证设置是否成功 + int actual_width = cap.get(CAP_PROP_FRAME_WIDTH); + int actual_height = cap.get(CAP_PROP_FRAME_HEIGHT); + double actual_fps = cap.get(CAP_PROP_FPS); + + printf("Requested resolution: %dx%d @ %d fps\n", width, height, fps); + printf("Actual resolution: %dx%d @ %.2f fps\n", actual_width, actual_height, actual_fps); + printf("Using format: %s\n", type_name); + + if (actual_width != width || actual_height != height) { + printf("Warning: Camera does not support requested resolution, using actual resolution\n"); + width = actual_width; + height = actual_height; + } + + // 初始化人脸检测器,使用更快的参数 + const string modelPath = "./onnx/face_detection_yunet_2023mar.onnx"; + Ptr detector = FaceDetectorYN::create( + /* 256 144 input width height 0.6 score_threshold 0.7 nms_threshold */ + modelPath, "", Size(256, 144), 0.6, 0.7, 100); /* 100 top_k */ + if (!detector) { + printf("Error: Failed to create face detector\n"); + return -1; + } + + // 初始化媒体链路 + if (sample_uvc_media_init(type_name, width, height) != TD_SUCCESS) { + std::cerr << "media start failed!" << std::endl; + return -1; + } + + const int MAX_RETRIES = 3; /* 3: max retries */ + int retry_count = 0; + bool device_reconnected = false; + int empty_frame_count = 0; + const int MAX_EMPTY_FRAMES = 10; /* 10: max empty frames */ + + // 预分配Mat对象 + Mat frame; + Mat faces; + Mat yuvFrame; + vector mjpeg_buffer; + mjpeg_buffer.reserve(width * height * 3 / 2); /* 3 / 2 YUV420 memory size */ + + // 创建MJPEG编码器 + vector mjpeg_params = { + IMWRITE_JPEG_QUALITY, 90, /* 90: JPEG quality */ + IMWRITE_JPEG_OPTIMIZE, 1, + IMWRITE_JPEG_PROGRESSIVE, 0 + }; + + // 预分配VPSS缓冲区 + ot_size pic_size; + pic_size.width = static_cast(width); + pic_size.height = static_cast(height); + + if (strcmp(type_name, "YUYV") == 0) { + // 预分配YUYV缓冲区,每个像素2字节 + yuvFrame.create(height, width, CV_8UC2); + } + + // 新增:人脸检测相关变量 + int frame_count = 0; + vector last_detected_faces; + vector last_confidence_scores; + const int DETECT_INTERVAL = 5; /* 5: Detect every 5 frames */ + + while (!g_uvc_exit) { + cap >> frame; + + if (frame.empty()) { + empty_frame_count++; + printf("Empty frame %d/%d, attempting to reconnect...\n", empty_frame_count, MAX_EMPTY_FRAMES); + + if (empty_frame_count >= MAX_EMPTY_FRAMES) { + if (retry_count < MAX_RETRIES) { + printf("Attempting to reconnect camera (attempt %d/%d)...\n", retry_count + 1, MAX_RETRIES); + cap.release(); + sleep(1); + + cap.open(0, cv::CAP_V4L2); + if (cap.isOpened()) { + cap.set(CAP_PROP_FRAME_WIDTH, width); + cap.set(CAP_PROP_FRAME_HEIGHT, height); + cap.set(CAP_PROP_FPS, fps); + cap.set(CAP_PROP_BUFFERSIZE, 4); /* 4 cap prop buffer size */ + if (strcmp(type_name, "MJPEG") == 0) { + cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G')); + } else { + cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('Y', 'U', 'Y', 'V')); + } + + actual_width = cap.get(CAP_PROP_FRAME_WIDTH); + actual_height = cap.get(CAP_PROP_FRAME_HEIGHT); + actual_fps = cap.get(CAP_PROP_FPS); + + printf("Camera reconnected successfully\n"); + printf("New resolution: %dx%d @ %.2f fps\n", actual_width, actual_height, actual_fps); + + retry_count = 0; + empty_frame_count = 0; + device_reconnected = true; + continue; + } + retry_count++; + printf("Retry %d/%d failed\n", retry_count, MAX_RETRIES); + } else { + printf("Failed to reconnect after %d attempts\n", MAX_RETRIES); + break; + } + } + continue; + } + + empty_frame_count = 0; + retry_count = 0; + + if (device_reconnected) { + printf("Reinitializing media pipeline...\n"); + if (sample_uvc_media_init(type_name, width, height) != TD_SUCCESS) { + std::cerr << "media reinit failed!" << std::endl; + break; + } + device_reconnected = false; + } + + // 人脸检测逻辑 + frame_count++; + bool is_detect_frame = (frame_count % DETECT_INTERVAL == 0); + + if (is_detect_frame) { + // 预处理阶段 + Mat small_frame; + resize(frame, small_frame, Size(256, 144), 0, 0, INTER_NEAREST); /* 256 144 resize width height */ + + // 检测阶段 + detector->detect(small_frame, faces); + + // 处理检测结果 + const int minFaceSize = 50; /* 50 min face size */ + last_detected_faces.clear(); + last_confidence_scores.clear(); + + if (faces.rows > 0) { + float scale_x = static_cast(frame.cols) / small_frame.cols; + float scale_y = static_cast(frame.rows) / small_frame.rows; + + for (int i = 0; i < faces.rows; ++i) { + int x = static_cast(faces.at(i, 0) * scale_x); + int y = static_cast(faces.at(i, 1) * scale_y); + int w = static_cast(faces.at(i, 2) * scale_x); /* 2 the number of width */ + int h = static_cast(faces.at(i, 3) * scale_y); /* 3 the number of heigth */ + float score = faces.at(i, 4); /* 4 the number of socre */ + + if (w >= minFaceSize && h >= minFaceSize) { + last_detected_faces.emplace_back(x, y, w, h); + last_confidence_scores.push_back(score); + } + } + } + } + + // 绘制人脸框 + for (size_t i = 0; i < last_detected_faces.size(); ++i) { + rectangle(frame, last_detected_faces[i], Scalar(0, 255, 0), 2); /* 0 255 0 R G B, 2 Line width */ + char scoreText[20]; /* 20 text buffer size */ + ret = snprintf(scoreText, sizeof(scoreText), "Conf: %.2f", + last_confidence_scores[i] / 100); /* 100 get the percentage */ + if (ret < 0) { + printf("[func]:%s [line]:%d [info]:snprintf failed\n", __FUNCTION__, __LINE__); + break; + } + putText(frame, scoreText, Point(last_detected_faces[i].x, + last_detected_faces[i].y - 5), /* 5 pic height minus 5 */ + /* 0.5 scaling ratio 0 255 0 R G B, 1 Line width */ + FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1); + } + + // 后续处理保持不变 + if (strcmp(type_name, "MJPEG") == 0) { + imencode(".jpg", frame, mjpeg_buffer, mjpeg_params); + ret = sample_uvc_media_send_data(mjpeg_buffer.data(), mjpeg_buffer.size(), + width, &pic_size, "MJPEG"); + } else { + // YUYV格式转换 + cvtColor(frame, yuvFrame, COLOR_BGR2YUV_YUY2); + ret = sample_uvc_media_send_data(yuvFrame.data, yuvFrame.total() * yuvFrame.elemSize(), + yuvFrame.step, &pic_size, "YUYV"); + } + + if (ret != 0) { + ret = -errno; + std::cerr << "write error: " << strerror(-ret) << std::endl; + } + } + + printf("--media exit...\n"); + sample_uvc_media_stop_receive_data(); + sample_uvc_media_exit(); + cap.release(); + +#ifdef CONFIG_USER_SPACE + SDK_exit(); +#endif + + return 0; +} \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/media_vdec.c b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/media_vdec.c new file mode 100755 index 0000000000000000000000000000000000000000..8afe3e73d0b97b8fed53b74f0256273f445f1e49 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/media_vdec.c @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "media_vdec.h" +#include + +ot_vb_src g_vdec_vb_source = OT_VB_SRC_MOD; + +#define REF_NUM 2 +#define DISPLAY_NUM 2 + +static vdec_display_cfg g_vdec_display_cfg = { + .pic_size = PIC_1080P, + .intf_sync = OT_VO_OUT_1080P60, + .intf_type = OT_VO_INTF_HDMI, +}; + +static td_u32 g_input_width; +static td_u32 g_input_height; +static ot_size g_disp_size; +sample_vo_cfg g_vo_config; +static td_bool g_is_need_vdec = TD_TRUE; + +static td_s32 sample_uvc_init_module_vb(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, ot_payload_type type, + td_u32 len) +{ + td_u32 i; + td_s32 ret; + for (i = 0; (i < vdec_chn_num) && (i < len); i++) { + sample_vdec[i].type = type; + sample_vdec[i].width = g_input_width; + sample_vdec[i].height = g_input_height; + sample_vdec[i].mode = sample_comm_vdec_get_lowdelay_en() ? OT_VDEC_SEND_MODE_COMPAT : + OT_VDEC_SEND_MODE_FRAME; + sample_vdec[i].sample_vdec_video.dec_mode = OT_VIDEO_DEC_MODE_IP; + sample_vdec[i].sample_vdec_video.bit_width = OT_DATA_BIT_WIDTH_8; + if (type == OT_PT_JPEG) { + sample_vdec[i].sample_vdec_video.ref_frame_num = 0; + } else { + sample_vdec[i].sample_vdec_video.ref_frame_num = REF_NUM; + } + sample_vdec[i].display_frame_num = DISPLAY_NUM; + sample_vdec[i].frame_buf_cnt = (type == OT_PT_JPEG) ? (sample_vdec[i].display_frame_num + 1) : + (sample_vdec[i].sample_vdec_video.ref_frame_num + sample_vdec[i].display_frame_num + 1); + if (type == OT_PT_JPEG) { + sample_vdec[i].sample_vdec_picture.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + sample_vdec[i].sample_vdec_picture.alpha = 255; /* 255:pic alpha value */ + } + } + ret = sample_comm_vdec_init_vb_pool(vdec_chn_num, &sample_vdec[0], len); + if (ret != TD_SUCCESS) { + sample_print("init mod common vb fail for %#x!\n", ret); + return ret; + } + return ret; +} + +static td_s32 sample_uvc_init_sys_and_vb(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, ot_payload_type type, + td_u32 len) +{ + ot_vb_cfg vb_cfg; + ot_pic_buf_attr buf_attr = {0}; + td_s32 ret; + ret = sample_comm_sys_get_pic_size(g_vdec_display_cfg.pic_size, &g_disp_size); + if (ret != TD_SUCCESS) { + sample_print("sys get pic size fail for %#x!\n", ret); + return ret; + } + buf_attr.align = 0; + buf_attr.bit_width = OT_DATA_BIT_WIDTH_8; + buf_attr.compress_mode = OT_COMPRESS_MODE_SEG; + buf_attr.height = 2160; /* 2160:height */ + buf_attr.width = 3840; /* 3840:width */ + buf_attr.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + + (td_void)memset_s(&vb_cfg, sizeof(ot_vb_cfg), 0, sizeof(ot_vb_cfg)); + vb_cfg.max_pool_cnt = 1; + vb_cfg.common_pool[0].blk_cnt = 10 * vdec_chn_num; /* 10:common vb cnt */ + vb_cfg.common_pool[0].blk_size = ot_common_get_pic_buf_size(&buf_attr); + ret = sample_comm_sys_init(&vb_cfg); + if (ret != TD_SUCCESS) { + sample_print("init sys fail for %#x!\n", ret); + sample_comm_sys_exit(); + return ret; + } + + if (g_is_need_vdec == TD_TRUE) { + ret = sample_uvc_init_module_vb(&sample_vdec[0], vdec_chn_num, type, len); + if (ret != TD_SUCCESS) { + sample_print("init mod vb fail for %#x!\n", ret); + sample_comm_vdec_exit_vb_pool(); + sample_comm_sys_exit(); + return ret; + } + } + + return ret; +} + +static td_s32 sample_uvc_vdec_bind_vpss(td_u32 vpss_grp_num) +{ + td_u32 i; + td_s32 ret = TD_SUCCESS; + for (i = 0; i < vpss_grp_num; i++) { + ret = sample_comm_vdec_bind_vpss(i, i); + if (ret != TD_SUCCESS) { + sample_print("vdec bind vpss fail for %#x!\n", ret); + return ret; + } + } + return ret; +} + +static td_void sample_uvc_stop_vpss(ot_vpss_grp vpss_grp, td_bool *vpss_chn_enable, td_u32 chn_array_size) +{ + td_s32 i; + for (i = vpss_grp; i >= 0; i--) { + vpss_grp = i; + sample_common_vpss_stop(vpss_grp, &vpss_chn_enable[0], chn_array_size); + } +} + +static td_s32 sample_uvc_vdec_unbind_vpss(td_u32 vpss_grp_num) +{ + td_u32 i; + td_s32 ret = TD_SUCCESS; + for (i = 0; i < vpss_grp_num; i++) { + ret = sample_comm_vdec_un_bind_vpss(i, i); + if (ret != TD_SUCCESS) { + sample_print("vdec unbind vpss fail for %#x!\n", ret); + } + } + return ret; +} + +static td_void sample_uvc_config_vpss_grp_attr(ot_vpss_grp_attr *vpss_grp_attr) +{ + vpss_grp_attr->max_width = g_input_width; + vpss_grp_attr->max_height = g_input_height; + vpss_grp_attr->frame_rate.src_frame_rate = -1; + vpss_grp_attr->frame_rate.dst_frame_rate = -1; + vpss_grp_attr->pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vpss_grp_attr->nr_en = TD_FALSE; + vpss_grp_attr->ie_en = TD_FALSE; + vpss_grp_attr->dci_en = TD_FALSE; + vpss_grp_attr->dei_mode = OT_VPSS_DEI_MODE_OFF; + vpss_grp_attr->buf_share_en = TD_FALSE; +} + +static td_void sample_uvc_stop_vdec(td_u32 vdec_chn_num) +{ + if (g_is_need_vdec == TD_FALSE) { + return; + } + sample_comm_vdec_stop(vdec_chn_num); + sample_comm_vdec_exit_vb_pool(); + + return; +} + +static td_s32 sample_uvc_start_vdec(sample_vdec_attr *sample_vdec, td_u32 vdec_chn_num, td_u32 len) +{ + td_s32 ret; + + if (g_is_need_vdec == TD_FALSE) { + return TD_SUCCESS; + } + ret = sample_comm_vdec_start(vdec_chn_num, &sample_vdec[0], len); + if (ret != TD_SUCCESS) { + sample_print("start VDEC fail for %#x!\n", ret); + sample_uvc_stop_vdec(vdec_chn_num); + } + + return ret; +} + +static td_s32 sample_uvc_config_vpss_ldy_attr(td_u32 vpss_grp_num) +{ + td_u32 i; + td_s32 ret; + ot_low_delay_info vpss_ldy_info; + + for (i = 0; i < vpss_grp_num; i++) { + ret = ss_mpi_vpss_get_low_delay_attr(i, 0, &vpss_ldy_info); + if (ret != TD_SUCCESS) { + sample_print("vpss get low delay attr fail for %#x!\n", ret); + return ret; + } + vpss_ldy_info.enable = TD_TRUE; + vpss_ldy_info.line_cnt = g_disp_size.height / 4 * 1; /* 1/4:lowdelay line num */ + ret = ss_mpi_vpss_set_low_delay_attr(i, 0, &vpss_ldy_info); + if (ret != TD_SUCCESS) { + sample_print("vpss set low delay attr fail for %#x!\n", ret); + return ret; + } + } + return TD_SUCCESS; +} + +static td_s32 sample_uvc_start_vpss(ot_vpss_grp *vpss_grp, td_u32 vpss_grp_num, + td_bool *vpss_chn_enable, td_u32 arr_len) +{ + td_u32 i; + td_s32 ret; + ot_vpss_chn_attr vpss_chn_attr[OT_VPSS_MAX_CHN_NUM]; + ot_vpss_grp_attr vpss_grp_attr = {0}; + sample_uvc_config_vpss_grp_attr(&vpss_grp_attr); + (td_void)memset_s(vpss_chn_enable, arr_len * sizeof(td_bool), 0, arr_len * sizeof(td_bool)); + if (arr_len > 1) { + vpss_chn_enable[0] = TD_TRUE; + vpss_chn_attr[0].width = g_disp_size.width; + vpss_chn_attr[0].height = g_disp_size.height; + vpss_chn_attr[0].chn_mode = OT_VPSS_CHN_MODE_USER; + vpss_chn_attr[0].compress_mode = OT_COMPRESS_MODE_NONE; + vpss_chn_attr[0].pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vpss_chn_attr[0].video_format = OT_VIDEO_FORMAT_LINEAR; + vpss_chn_attr[0].frame_rate.src_frame_rate = -1; + vpss_chn_attr[0].frame_rate.dst_frame_rate = -1; + vpss_chn_attr[0].depth = 0; + vpss_chn_attr[0].mirror_en = TD_FALSE; + vpss_chn_attr[0].flip_en = TD_FALSE; + vpss_chn_attr[0].border_en = TD_FALSE; + vpss_chn_attr[0].aspect_ratio.mode = OT_ASPECT_RATIO_NONE; + } + + for (i = 0; i < vpss_grp_num; i++) { + *vpss_grp = i; + ret = sample_common_vpss_start(*vpss_grp, &vpss_chn_enable[0], + &vpss_grp_attr, vpss_chn_attr, OT_VPSS_MAX_CHN_NUM); + if (ret != TD_SUCCESS) { + sample_print("start VPSS fail for %#x!\n", ret); + sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + return ret; + } + } + ret = sample_uvc_config_vpss_ldy_attr(vpss_grp_num); + if (ret != TD_SUCCESS) { + sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + return ret; + } + ret = sample_uvc_vdec_bind_vpss(vpss_grp_num); + if (ret != TD_SUCCESS) { + sample_uvc_vdec_unbind_vpss(vpss_grp_num); + sample_uvc_stop_vpss(*vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + } + return ret; +} + +static td_s32 sample_uvc_vpss_bind_vo(sample_vo_cfg vo_config, td_u32 vpss_grp_num) +{ + td_u32 i; + ot_vo_layer vo_layer; + td_s32 ret = TD_SUCCESS; + vo_layer = vo_config.vo_dev; + for (i = 0; i < vpss_grp_num; i++) { + ret = sample_comm_vpss_bind_vo(i, 0, vo_layer, i); + if (ret != TD_SUCCESS) { + sample_print("vpss bind vo fail for %#x!\n", ret); + return ret; + } + } + return ret; +} + +static td_s32 sample_uvc_vpss_unbind_vo(td_u32 vpss_grp_num, sample_vo_cfg vo_config) +{ + td_u32 i; + ot_vo_layer vo_layer = vo_config.vo_dev; + td_s32 ret = TD_SUCCESS; + for (i = 0; i < vpss_grp_num; i++) { + ret = sample_comm_vpss_un_bind_vo(i, 0, vo_layer, i); + if (ret != TD_SUCCESS) { + sample_print("vpss unbind vo fail for %#x!\n", ret); + } + } + return ret; +} + +static td_void sample_uvc_get_default_vo_cfg(sample_vo_cfg *vo_config) +{ + vo_config->vo_dev = SAMPLE_VO_DEV_UHD; + vo_config->vo_intf_type = g_vdec_display_cfg.intf_type; + vo_config->intf_sync = g_vdec_display_cfg.intf_sync; + vo_config->pic_size = g_vdec_display_cfg.pic_size; + vo_config->bg_color = COLOR_RGB_BLUE; + vo_config->dis_buf_len = 3; /* 3:buf length */ + vo_config->dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8; + vo_config->vo_mode = VO_MODE_1MUX; + vo_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + vo_config->disp_rect.x = 0; + vo_config->disp_rect.y = 0; + vo_config->disp_rect.width = g_disp_size.width; + vo_config->disp_rect.height = g_disp_size.height; + vo_config->image_size.width = g_disp_size.width; + vo_config->image_size.height = g_disp_size.height; + vo_config->vo_part_mode = OT_VO_PARTITION_MODE_SINGLE; + vo_config->compress_mode = OT_COMPRESS_MODE_NONE; +} + +static td_s32 sample_uvc_start_vo(sample_vo_cfg *vo_config, td_u32 vpss_grp_num) +{ + td_s32 ret; + sample_uvc_get_default_vo_cfg(vo_config); + ret = sample_comm_vo_start_vo(vo_config); + if (ret != TD_SUCCESS) { + sample_print("start VO fail for %#x!\n", ret); + sample_comm_vo_stop_vo(vo_config); + return ret; + } + ret = sample_uvc_vpss_bind_vo(*vo_config, vpss_grp_num); + if (ret != TD_SUCCESS) { + sample_uvc_vpss_unbind_vo(vpss_grp_num, *vo_config); + sample_comm_vo_stop_vo(vo_config); + } + + return ret; +} + +static ot_payload_type sample_uvc_get_payload_type(const td_char *type_name) +{ + if (strcmp(type_name, "H264") == 0) { + return OT_PT_H264; + } else if (strcmp(type_name, "H265") == 0) { + return OT_PT_H265; + } else if (strcmp(type_name, "MJPEG") == 0) { + return OT_PT_JPEG; + } else { + sample_print("type name error!\n"); + return OT_PT_BUTT; + } +} + +static td_void sample_uvc_update_vdec_flag(const td_char *type_name) +{ + if ((strcmp(type_name, "H264") == 0) || + (strcmp(type_name, "H265") == 0) || + (strcmp(type_name, "MJPEG") == 0)) { + g_is_need_vdec = TD_TRUE; + } else { + g_is_need_vdec = TD_FALSE; + } +} + +td_s32 sample_uvc_media_init(const td_char *type_name, td_u32 width, td_u32 height) +{ + td_s32 ret; + td_u32 vdec_chn_num; + td_u32 vpss_grp_num; + sample_vdec_attr sample_vdec[OT_VDEC_MAX_CHN_NUM]; + td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM]; + ot_vpss_grp vpss_grp; + + ot_payload_type payload_type = OT_PT_H264; + vdec_chn_num = 1; + vpss_grp_num = vdec_chn_num; + g_input_width = width; + g_input_height = height; + sample_uvc_update_vdec_flag(type_name); + + if (g_is_need_vdec == TD_TRUE) { + payload_type = sample_uvc_get_payload_type(type_name); + if (payload_type == OT_PT_BUTT) { + return TD_FAILURE; + } + } + ret = sample_uvc_init_sys_and_vb(&sample_vdec[0], vdec_chn_num, payload_type, OT_VDEC_MAX_CHN_NUM); + if (ret != TD_SUCCESS) { + return ret; + } + ret = sample_uvc_start_vdec(&sample_vdec[0], vdec_chn_num, OT_VDEC_MAX_CHN_NUM); + if (ret != TD_SUCCESS) { + goto stop_sys; + } + ret = sample_uvc_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + if (ret != TD_SUCCESS) { + goto stop_vdec; + } + ret = sample_uvc_start_vo(&g_vo_config, vpss_grp_num); + if (ret != TD_SUCCESS) { + goto stop_vpss; + } + + return TD_SUCCESS; + +stop_vpss: + ret = sample_uvc_vdec_unbind_vpss(vpss_grp_num); + sample_uvc_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); +stop_vdec: + sample_uvc_stop_vdec(vdec_chn_num); +stop_sys: + sample_comm_sys_exit(); + + return TD_FAILURE; +} + +td_s32 sample_uvc_media_exit(td_void) +{ + td_u32 vdec_chn_num = 1; + td_u32 vpss_grp_num = 1; + ot_vpss_grp vpss_grp = 0; + td_bool vpss_chn_enable[OT_VPSS_MAX_CHN_NUM] = {0}; + vpss_chn_enable[0] = TD_TRUE; + + (td_void)sample_uvc_vpss_unbind_vo(vpss_grp_num, g_vo_config); + sample_comm_vo_stop_vo(&g_vo_config); + (td_void)sample_uvc_vdec_unbind_vpss(vpss_grp_num); + sample_uvc_stop_vpss(vpss_grp, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM); + sample_uvc_stop_vdec(vdec_chn_num); + sample_comm_sys_exit(); + + return TD_SUCCESS; +} + +static td_void sample_uvc_cut_stream_for_mjpeg(td_void *data, td_u32 size, td_s32 chn_id, + td_s32 *read_num, td_u32 *start) +{ + td_s32 i; + td_u32 len; + td_s32 read_len = size; + td_u8 *buf = data; + td_bool find_start = TD_FALSE; + for (i = 0; i < read_len - 1; i++) { + if (buf[i] == 0xFF && buf[i + 1] == 0xD8) { /* 0xFFD8: JPEG起始标记 */ + *start = i; + find_start = TD_TRUE; + i = i + 2; /* 2: 跳过标记长度 */ + break; + } + } + + /* 3: 检查下一个标记头所需长度 */ + for (; i < read_len - 3; i++) { + if ((buf[i] == 0xFF) && (buf[i + 1] & 0xF0) == 0xE0) { + len = (buf[i + 2] << 8) + buf[i + 3]; /* 2 3 index 8: 长度字段占2字节 */ + i += 1 + len; + } else { + break; + } + } + + for (; i < read_len - 1; i++) { + if (buf[i] == 0xFF && buf[i + 1] == 0xD9) { /* 0xFFD9: JPEG结束标记 */ + break; + } + } + read_len = i + 2; /* 2: 包含结束标记 */ + + if (find_start == TD_FALSE) { + sample_print("chn %d can not find JPEG start code! read_len %d!\n", chn_id, read_len); + } + + *read_num = read_len; +} + +static td_void sample_uvc_cut_stream_for_h264(td_void *data, td_u32 size, td_s32 chn_id, td_s32 *read_num) +{ + td_bool find_start = TD_FALSE; + td_bool find_end = TD_FALSE; + td_s32 i; + td_u8 *buf = data; + td_s32 read_len = size; + for (i = 0; i < read_len - 8; i++) { /* 8: 起始码最小长度 */ + int tmp = buf[i + 3] & 0x1F; /* 0x1F: NALU类型掩码 */ + /* 0x5: IDR帧, 0x1: 非IDR帧 0x80: 关键帧标志 2 index */ + if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && + (((tmp == 0x5 || tmp == 0x1) && ((buf[i + 4] & 0x80) == 0x80)) || /* 4 index */ + (tmp == 20 && (buf[i + 7] & 0x80) == 0x80))) { /* 20 帧起始类型 7 index */ + find_start = TD_TRUE; + i += 8; /* 8: 跳过起始码 */ + break; + } + } + + for (; i < read_len - 8; i++) { /* 8: 查找结束所需最小长度 */ + int tmp = buf[i + 3] & 0x1F; /* 0x1F: NALU类型掩码 */ + if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && /* 2 index */ + (tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6 || /* 15 SEI 7 SPS 8 PPS 6 SEI */ + ((tmp == 5 || tmp == 1) && ((buf[i + 4] & 0x80) == 0x80)) || /* 5 1 帧起始类型 4 index */ + (tmp == 20 && (buf[i + 7] & 0x80) == 0x80))) { /* 20 帧起始类型 7 index */ + find_end = TD_TRUE; + break; + } + } + + if (i > 0) { + read_len = i; + } + + if (find_start == TD_FALSE) { + sample_print("chn %d can not find H264 start code! read_len %d!\n", chn_id, read_len); + } + + if (find_end == TD_FALSE) { + read_len = i + 8; /* 8: 包含下一帧起始码 */ + } + + *read_num = read_len; +} + +static td_void sample_uvc_cut_stream_for_h265(td_void *data, td_u32 size, td_s32 chn_id, td_s32 *read_num) +{ + td_bool find_start = TD_FALSE; + td_bool find_end = TD_FALSE; + td_bool new_pic = TD_FALSE; + td_s32 i; + td_u8 *buf = data; + td_s32 read_len = size; + for (i = 0; i < read_len - 6; i++) { /* 6:h265 frame start code length */ + td_u32 tmp = (buf[i + 3] & 0x7E) >> 1; /* 0x7E:frame start marker 3:index */ + new_pic = (buf[i + 0] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && /* 1 2:index */ + (tmp <= 21) && ((buf[i + 5] & 0x80) == 0x80)); /* 5:index 21 0x80:frame start marker */ + + if (new_pic) { + find_start = TD_TRUE; + i += 6; /* 6:h265 frame start code length */ + break; + } + } + + for (; i < read_len - 6; i++) { /* 6:h265 frame start code length */ + td_u32 tmp = (buf[i + 3] & 0x7E) >> 1; /* 0x7E:frame start marker 3:index */ + new_pic = (buf[i + 0] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && /* 1 2:index */ + (tmp == 32 || tmp == 33 || tmp == 34 || tmp == 39 || tmp == 40 || /* 32 33 34 39 40:frame start marker */ + ((tmp <= 21) && (buf[i + 5] & 0x80) == 0x80))); /* 5:index 21 0x80:frame start marker */ + + if (new_pic) { + find_end = TD_TRUE; + break; + } + } + + if (i > 0) { + read_len = i; + } + + if (find_start == TD_FALSE) { + sample_print("chn %d can not find H265 start code! read_len %d!\n", chn_id, read_len); + } + + if (find_end == TD_FALSE) { + read_len = i + 6; /* 6:h265 frame start code length */ + } + + *read_num = read_len; +} + +static td_s32 sample_uvc_prepare_frame_info(ot_vb_blk vb_blk, const ot_pic_buf_attr *buf_attr, + const ot_vb_calc_cfg *calc_cfg, ot_video_frame_info *video_frame) +{ + video_frame->video_frame.header_phys_addr[0] = ss_mpi_vb_handle_to_phys_addr(vb_blk); + if (video_frame->video_frame.header_phys_addr[0] == TD_NULL) { + sample_print("ss_mpi_vb_handle_to_phys_addr fail\n"); + return TD_FAILURE; + } + + video_frame->video_frame.header_virt_addr[0] = + (td_u8*)ss_mpi_sys_mmap(video_frame->video_frame.header_phys_addr[0], calc_cfg->vb_size); + if (video_frame->video_frame.header_virt_addr[0] == TD_NULL) { + sample_print("ss_mpi_sys_mmap fail\n"); + return TD_FAILURE; + } + + video_frame->mod_id = OT_ID_VGS; + video_frame->pool_id = ss_mpi_vb_handle_to_pool_id(vb_blk); + + video_frame->video_frame.header_phys_addr[1] = + video_frame->video_frame.header_phys_addr[0] + calc_cfg->head_y_size; + video_frame->video_frame.header_virt_addr[1] = + video_frame->video_frame.header_virt_addr[0] + calc_cfg->head_y_size; + video_frame->video_frame.phys_addr[0] = + video_frame->video_frame.header_phys_addr[0] + calc_cfg->head_size; + video_frame->video_frame.phys_addr[1] = + video_frame->video_frame.phys_addr[0] + calc_cfg->main_y_size; + video_frame->video_frame.virt_addr[0] = + video_frame->video_frame.header_virt_addr[0] + calc_cfg->head_size; + video_frame->video_frame.virt_addr[1] = + video_frame->video_frame.virt_addr[0] + calc_cfg->main_y_size; + video_frame->video_frame.header_stride[0] = calc_cfg->head_stride; + video_frame->video_frame.header_stride[1] = calc_cfg->head_stride; + video_frame->video_frame.stride[0] = calc_cfg->main_stride; + video_frame->video_frame.stride[1] = calc_cfg->main_stride; + + video_frame->video_frame.width = buf_attr->width; + video_frame->video_frame.height = buf_attr->height; + video_frame->video_frame.dynamic_range = OT_DYNAMIC_RANGE_SDR8; + video_frame->video_frame.compress_mode = OT_COMPRESS_MODE_NONE; + video_frame->video_frame.video_format = OT_VIDEO_FORMAT_LINEAR; + video_frame->video_frame.field = OT_VIDEO_FIELD_FRAME; + video_frame->video_frame.pixel_format = OT_PIXEL_FORMAT_YUV_SEMIPLANAR_420; + + return TD_SUCCESS; +} + +static td_void sample_uvc_buf_attr_init(const ot_size *pic_size, ot_pic_buf_attr *buf_attr) +{ + buf_attr->width = pic_size->width; + buf_attr->height = pic_size->height; + buf_attr->pixel_format = OT_PIXEL_FORMAT_YUV_SEMIPLANAR_420; + buf_attr->compress_mode = OT_COMPRESS_MODE_NONE; + buf_attr->align = 0; + buf_attr->bit_width = OT_DATA_BIT_WIDTH_8; +} + +static td_void sample_uvc_yuyv_to_nv12(td_char *image_in, td_u32 width, td_u32 height, + td_u32 size, td_char *image_out) +{ + td_s32 pixel_num = width * height; + td_u32 cycle_num = size / pixel_num / 2; /* 2: YUYV格式中每个像素占2字节 */ + + td_char *y = image_out; + td_char *uv = image_out + pixel_num; + + td_char *start = image_in; + td_u32 i = 0; + td_u32 j = 0; + td_u32 k = 0; + + /* Y */ + for (i = 0; i < cycle_num; i++) { + int index = 0; + for (j = 0; j < pixel_num * 2; j = j + 2) { /* 2: 跳过UV分量,每次取Y */ + *(y + index) = *(start + j); + index++; + } + start = image_in + pixel_num * 2 * i; /* 2: 每帧YUYV数据跨度 */ + y = y + pixel_num * 3 / 2; /* 3/2: NV12中Y+UV的总大小比例 */ + } + + /* UV */ + start = image_in; + for (i = 0; i < cycle_num; i++) { + int uv_index = 0; + for (j = 0; j < height; j = j + 2) { /* 2: 隔行采样UV */ + /* 2: YUYV宽度步进 4: 每两个像素的YUYV数据块 1: 取U分量的位置偏移 2: 取下一个V分量的偏移 */ + for (k = j * width * 2 + 1; k < width * 2 * (j + 1); k = k + 4) { + *(uv + uv_index) = *(start + k); /* U分量 */ + *(uv + uv_index + 1) = *(start + k + 2); /* 2 取下一个V分量的偏移 */ + uv_index += 2; /* 2: UV平面存储步进 */ + } + } + start = image_in + pixel_num * 2 * i; /* 2: 每帧YUYV数据跨度 */ + uv = uv + pixel_num * 3 / 2; /* 3/2: NV12中Y+UV的总大小比例 */ + } +} + +static td_void sample_uvc_update_vb_cfg(ot_pixel_format pixel_format, td_u32 stride, const ot_size *pic_size, + ot_vb_calc_cfg *calc_cfg) +{ + if (pixel_format != OT_PIXEL_FORMAT_YUYV_PACKAGE_422) { + return; + } + + calc_cfg->main_stride = stride >> 1; + calc_cfg->main_y_size = calc_cfg->main_stride * pic_size->height; +} + +static td_s32 sample_uvc_send_frame_to_vpss(td_void *data, td_u32 size, td_u32 stride, + const ot_size *pic_size, ot_pixel_format pixel_format) +{ + td_s32 ret; + ot_vpss_grp grp = 0; + ot_video_frame_info frame_info = {0}; + td_s32 milli_sec = -1; + ot_vb_blk vb_blk; + ot_pic_buf_attr buf_attr; + ot_vb_calc_cfg calc_cfg; + sample_uvc_buf_attr_init(pic_size, &buf_attr); + ot_common_get_pic_buf_cfg(&buf_attr, &calc_cfg); + sample_uvc_update_vb_cfg(pixel_format, stride, pic_size, &calc_cfg); + vb_blk = ss_mpi_vb_get_blk(OT_VB_INVALID_POOL_ID, calc_cfg.vb_size, TD_NULL); + if (vb_blk == OT_VB_INVALID_HANDLE) { + sample_print("get vb blk(size:%d) failed!\n", calc_cfg.vb_size); + return TD_FAILURE; + } + ret = sample_uvc_prepare_frame_info(vb_blk, &buf_attr, &calc_cfg, &frame_info); + if (ret != TD_SUCCESS) { + return ret; + } + + if (pixel_format == OT_PIXEL_FORMAT_YUYV_PACKAGE_422) { + sample_uvc_yuyv_to_nv12(data, pic_size->width, pic_size->height, size, frame_info.video_frame.virt_addr[0]); + } else { + frame_info.video_frame.pixel_format = pixel_format; + (td_void)memcpy_s(frame_info.video_frame.virt_addr[0], size, data, size); + } + ret = ss_mpi_vpss_send_frame(grp, &frame_info, milli_sec); + if (ret != TD_SUCCESS) { + sample_print("send frame to vpss failed!\n"); + } + ss_mpi_sys_munmap(frame_info.video_frame.virt_addr[0], calc_cfg.vb_size); + ret = ss_mpi_vb_release_blk(vb_blk); + if (ret != TD_SUCCESS) { + sample_print("release vb failed!\n"); + return TD_FAILURE; + } + + return ret; +} + +static td_s32 sample_uvc_get_pixel_format(const td_char *type_name, ot_pixel_format *pixel_format) +{ + if (strcmp(type_name, "YUYV") == 0) { + *pixel_format = OT_PIXEL_FORMAT_YUYV_PACKAGE_422; + } else if (strcmp(type_name, "NV12") == 0) { + *pixel_format = OT_PIXEL_FORMAT_YUV_SEMIPLANAR_420; + } else if (strcmp(type_name, "NV21") == 0) { + *pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; + } else { + sample_print("pixel format error!\n"); + return TD_FAILURE; + } + + return TD_SUCCESS; +} + +td_s32 sample_uvc_media_send_data(td_void *data, td_u32 size, td_u32 stride, + const ot_size *pic_size, const td_char *type_name) +{ + td_bool end_of_stream = TD_FALSE; + td_s32 read_len = size; + td_u8 *buf = data; + ot_vdec_stream vdec_stream; + td_u32 start = 0; + td_s32 ret; + td_s32 chn_id = 0; + ot_pixel_format pixel_format; + td_bool send_again = TD_TRUE; + + if (strcmp(type_name, "MJPEG") == 0) { + sample_uvc_cut_stream_for_mjpeg(data, size, chn_id, &read_len, &start); + } else if (strcmp(type_name, "H264") == 0) { + sample_uvc_cut_stream_for_h264(data, size, chn_id, &read_len); + } else if (strcmp(type_name, "H265") == 0) { + sample_uvc_cut_stream_for_h265(data, size, chn_id, &read_len); + } else { + ret = sample_uvc_get_pixel_format(type_name, &pixel_format); + if (ret != TD_SUCCESS) { + return ret; + } + return sample_uvc_send_frame_to_vpss(data, size, stride, pic_size, pixel_format); + } + + vdec_stream.addr = buf + start; + vdec_stream.len = read_len; + vdec_stream.end_of_frame = TD_TRUE; + vdec_stream.end_of_stream = end_of_stream; + vdec_stream.need_display = 1; + + while (send_again == TD_TRUE) { + ss_mpi_sys_get_cur_pts(&vdec_stream.pts); + ret = ss_mpi_vdec_send_stream(chn_id, &vdec_stream, 0); + if (ret != TD_SUCCESS) { + usleep(1000); /* 1000 sleep 1000us */ + sample_print("send stream to vdec failed!\n"); + continue; + } else { + end_of_stream = TD_FALSE; + } + send_again = TD_FALSE; + } + usleep(1000); /* 1000 sleep 1000us */ + + return TD_SUCCESS; +} + +td_s32 sample_uvc_media_stop_receive_data(td_void) +{ + ot_vdec_stream vdec_stream = {0}; + td_u32 vdec_chn_num = 1; + td_s32 chn_id = 0; + + if (g_is_need_vdec == TD_FALSE) { + return TD_SUCCESS; + } + + vdec_stream.end_of_stream = TD_TRUE; + ss_mpi_vdec_send_stream(chn_id, &vdec_stream, -1); + ss_mpi_vdec_stop_recv_stream(vdec_chn_num); + + return TD_SUCCESS; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/media_vdec.h b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/media_vdec.h new file mode 100755 index 0000000000000000000000000000000000000000..dcd6942734b98e09e5befc75a6cac348d7fa38c8 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/media_vdec.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MEDIA_VDEC_H__ +#define __MEDIA_VDEC_H__ + +#include "sample_comm.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +td_s32 sample_uvc_media_init(const td_char *type_name, td_u32 width, td_u32 height); +td_s32 sample_uvc_media_exit(td_void); +td_s32 sample_uvc_media_send_data(td_void *data, td_u32 data_size, td_u32 stride, + const ot_size *pic_size, const td_char *type_name); +td_s32 sample_uvc_media_stop_receive_data(td_void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + + +#endif /* end of #ifndef __MEDIA_VDEC_H__ */ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/onnx/face_detection_yunet_2023mar.onnx b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/onnx/face_detection_yunet_2023mar.onnx new file mode 100755 index 0000000000000000000000000000000000000000..f9beb3044f3791affe1c2f0932af31927e2e4705 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/onnx/face_detection_yunet_2023mar.onnx differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20221114150205685.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20221114150205685.png new file mode 100755 index 0000000000000000000000000000000000000000..4dc4215c962c57ba0e31548fb98c29c789f149d9 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20221114150205685.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250210161601541.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250210161601541.png new file mode 100755 index 0000000000000000000000000000000000000000..80845ece8131933a4cd56ae3bd6119c38e0abd26 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250210161601541.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250210170027454.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250210170027454.png new file mode 100755 index 0000000000000000000000000000000000000000..c06081fc2c963af4d1fa8af506804beedefe1b0b Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250210170027454.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250213112932380.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250213112932380.png new file mode 100755 index 0000000000000000000000000000000000000000..8b591b3437544859f4ec76b9ca03867cc401078c Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250213112932380.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919150630870.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919150630870.png new file mode 100755 index 0000000000000000000000000000000000000000..91f881e85b3292118336ce2c3d81968e4aee8c26 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919150630870.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919151018659.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919151018659.png new file mode 100755 index 0000000000000000000000000000000000000000..9b09507893b65d2142be49e6461daa31a81855c4 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919151018659.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919151519310.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919151519310.png new file mode 100755 index 0000000000000000000000000000000000000000..7f6d881a5d0e6d3f72b7a43d089b5c5a75d7f048 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919151519310.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181207847.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181207847.png new file mode 100755 index 0000000000000000000000000000000000000000..08df0f6a6eb2e5c602d2b818c18347651384099b Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181207847.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181826651.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181826651.png new file mode 100755 index 0000000000000000000000000000000000000000..aaab3c4c1e0461bcd92fe63139841fddde7f7ba0 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181826651.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181855261.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181855261.png new file mode 100755 index 0000000000000000000000000000000000000000..b629a8f13c23348fb7267180b4f47e1aa3b065ce Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919181855261.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182525339.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182525339.png new file mode 100755 index 0000000000000000000000000000000000000000..6c4d223c9998d82e2c72cf1d5461aa373f0ed880 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182525339.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182655395.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182655395.png new file mode 100755 index 0000000000000000000000000000000000000000..e43e99ff241013e06a69b330ac0afdc683156472 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182655395.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182937455.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182937455.png new file mode 100755 index 0000000000000000000000000000000000000000..1eb3de878098d1f78e8a36fd78a56d54ea197de9 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919182937455.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183224310.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183224310.png new file mode 100755 index 0000000000000000000000000000000000000000..b539dd4175d5937062827ba614b2993165d510e4 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183224310.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183401330.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183401330.png new file mode 100755 index 0000000000000000000000000000000000000000..bea2b8acdd54f9eb7146a598b91c48da8895e0de Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183401330.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183513040.png b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183513040.png new file mode 100755 index 0000000000000000000000000000000000000000..d31cf4f5366f15bfeca2abc2cbf1999eab8cd3f2 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/opencv_dnn/pic/image-20250919183513040.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/Makefile b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..3f3058a2e4d124d2bd7ecd595e454f3bf817acd4 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/Makefile @@ -0,0 +1,48 @@ +# 编译所需的公共文件 +include ../mk.param + +# 编译后生成的可执行文件名 +TARGET := main + +# 编译此工程需要包含的头文件 +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR)/ +CFLAGS += -I$(SDK_SAMPLE_COMMON_DIR)/ +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR)/svp_npu +CFLAGS += -I$(KCF_TRACK_SAMPLE_DIR)/ + +# 编译此工程需要依赖的.c或.cpp文件 +SMP_SRCS := $(SDK_SAMPLE_COMMON_DIR)/sample_comm_sys.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_ipc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_isp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vi.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vo.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_mipi_tx.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vpss.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/loadbmp.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_vdec.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sample_comm_venc.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_init.c +SMP_SRCS += $(SDK_SAMPLE_COMMON_DIR)/sdk_exit.c +SMP_SRCS += $(wildcard $(SVP_COMMON_DIR)/*.c) +SMP_SRCS += $(KCF_TRACK_SAMPLE_DIR)/main.c +SMP_SRCS += $(KCF_TRACK_SAMPLE_DIR)/sample_kcf_track.c +SMP_SRCS += $(KCF_TRACK_SAMPLE_DIR)/sample_svp_npu_process.c + +# 编译此工程需要包含的库和宏 +CFLAGS += -O3 -g -Wall -DUSE_USB_CAMERA +CFLAGS += -fstack-protector-strong + +# 根据实际的类型设置,可以用set_sensor脚本设置 +SENSOR0_TYPE = -DSENSOR0_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR1_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR2_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT +SENSOR3_TYPE = -DSENSOR1_TYPE=HY_S0603_MIPI_8M_30FPS_12BIT + +CFLAGS += $(SENSOR0_TYPE) +CFLAGS += $(SENSOR1_TYPE) +CFLAGS += $(SENSOR2_TYPE) +CFLAGS += $(SENSOR3_TYPE) +# 编译工程所需的mk文件 + +include ../sdk_linux.mk + diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/README.md b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/README.md new file mode 100755 index 0000000000000000000000000000000000000000..85f586108390ebdb743bf7811af1d6f0b6c5ea4a --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/README.md @@ -0,0 +1,140 @@ +## 2.4、sample_kcf_track操作指导 + +### 2.4.1、sample_kcf_track程序简介 + +* sample_kcf_track 基于SS928V100平台开发,以EulerPi套件为例,sample_kcf_track 基于KCF+Track模型,通过USB Camera,将采集到的图片送到KFC+trak模型,实现对目标的实时跟踪效果。 + +### 2.4.2、目录 + +```shell +pegasus/vendor/cust/demo/sample_kcf_track +|── main.c # sample_kcf_track的主入口 +|── Makefile # 编译脚本 +|── sample_kcf_track.c # sample_kcf_track业务代码 +|── sample_kcf_track.h # sample_kcf_track业务代码头文件 +|── sample_svp_npu_process.c # 调用SVP_NPU的业务代码 +└── sample_svp_npu_process.c # 调用SVP_NPU的头文件 +``` + +![image-20250919184816530](pic/image-20250919184816530.png) + +### 2.4.3、编译 + +* **注意:在编译cust的demo之前,请确保你已经按照[patch介绍中的步骤](../../README.md#4patch介绍)把补丁打入海思SDK的sample目录下了**。 + +* 步骤1:先根据自己选择的操作系统,进入到对应的Pegasus所在目录下。 + +* 步骤2:使用Makefile的方式进行单编 + +* 在Ubuntu的命令行终端,分步执行下面的命令,单编 sample_kcf_track + + ``` + cd pegasus/vendor/cust/demo/sample_kcf_track + + make clean && make + ``` + + ![image-20250919185144994](pic/image-20250919185144994.png) + + * 在sample_kcf_track目录下,生成一个名为sample_kcf_track的 可执行文件,如下图所示: + + ![image-20250919185208004](pic/image-20250919185208004.png) + +### 2.4.4、拷贝可执行程序和依赖文件至开发板的mnt目录下 + +**方式一:使用SD卡进行资料文件的拷贝** + +* 首先需要自己准备一张Micro sd卡(16G 左右即可),还得有一个Micro sd卡的读卡器。 + +image-20221114150205685 + +* 步骤1:将编译后生成的可执行文件拷贝到SD卡中。 + +![image-20250919191302486](pic/image-20250919191302486.png) + +* 步骤2:可执行文件拷贝成功后,将内存卡插入开发板的SD卡槽中,可通过挂载的方式挂载到板端,可选择SD卡 mount指令进行挂载。 + +image-20250210161601541 + +* 在开发板的终端,执行下面的命令进行SD卡的挂载 + * 如果挂载失败,可以参考[这个issue尝试解决](https://gitee.com/HiSpark/HiSpark_NICU2022/issues/I54932?from=project-issue) + + +```shell +mount -t vfat /dev/mmcblk1p1 /mnt +# 其中/dev/mmcblk1p1需要根据实际块设备号修改 +``` + +* 挂载成功后,如下图所示: + +![image-20250919192508575](pic/image-20250919192508575.png) + +**方式二:使用NFS挂载的方式进行资料文件的拷贝** + +* 首先需要自己准备一根网线 +* 步骤1:参考[博客链接](https://blog.csdn.net/Wu_GuiMing/article/details/115872995?spm=1001.2014.3001.5501)中的内容,进行nfs的环境搭建 +* 步骤2:将编译后生成的可执行文件拷贝到Windows的nfs共享路径下 + +![image-20250919191208927](pic/image-20250919191208927.png) + +* 步骤3:在开发板的终端执行下面的命令,将Windows的nfs共享路径挂载至开发板的mnt目录下 + * 注意:这里IP地址请根据你开发板和电脑主机的实际IP地址进行填写 + + +``` +ifconfig eth0 192.168.100.100 + +mount -o nolock,addr=192.168.100.10 -t nfs 192.168.100.10:/d/nfs /mnt +``` + +![image-20250919191401771](pic/image-20250919191401771.png) + +### 2.4.5、硬件连接 + +* 准备一个外接显示器和HDMI数据线,将HDMI的一头接在开发板的HDMI输出口,将HDMI的另外一头接在外接显示器的HDMI输入口。 + +![image-20250213112932380](pic/image-20250213112932380.png) + +* 将USB 摄像头接在EulerPi开发板的USB接口上。 + +image-20250919150630870 + +### 2.4.6、功能验证 + +* 在开发板的终端执行下面的命令,运行可执行文件 + +``` +cd /mnt + +chmod +x sample_kcf_track + +./sample_kcf_track +``` + +![image-20250919191456754](pic/image-20250919191456754.png) + +* 此时,在HDMI的外接显示屏上即可出现实时码流,如下图所示: + +image-20250210170027454 + +* 如果您看到的现象和下图现象不一致,可以确认一下USB涉嫌头是否插入到开发板的USB口,并且在开发板的/dev目录下能够看到video0 和 video1两个设备节点。如果没有这两个设备节点,请确保镜像烧录正常。 + +![image-20250919151018659](pic/image-20250919151018659.png) + +* 正常情况下,我们会在外接显示屏上看到USB Camera采集到的画面。 +* 步骤1:按下键盘的空格键,会在屏幕的正中间显示一个红色的框框。 + +![image-20250919192349341](pic/image-20250919192349341.png) + +* 步骤2:把需要跟踪的目标放在红色框框内,然后再按一下空格键,此时红色框会变绿,如果没有变,可以重复一次。 +* 步骤3:移动需要跟踪的目标,绿色框会跟着目标一起移动。 + +![image-20250919192115350](pic/image-20250919192137187.png) + +* 当目标不在sensor视野范围内,绿框会变成黄色。 + +![image-20250919192243361](pic/image-20250919192243361.png) + +* 输入Q键,即可关闭程序 + +![image-20250919151519310](pic/image-20250919151519310.png) \ No newline at end of file diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/main.c b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/main.c new file mode 100755 index 0000000000000000000000000000000000000000..62a2b7375f57999d236528a96dcb25fe145f8758 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/main.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdk_module_init.h" +#include "securec.h" +#include "sample_svp_npu_process.h" + +int main(int argc, char *argv[]) +{ + td_s32 ret; + +#ifdef CONFIG_USER_SPACE + SDK_init(); +#endif + + sample_svp_npu_acl_v4l2_kcf(); + +#ifdef CONFIG_USER_SPACE + SDK_exit(); +#endif + return 0; +} diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20221114150205685.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20221114150205685.png new file mode 100755 index 0000000000000000000000000000000000000000..4dc4215c962c57ba0e31548fb98c29c789f149d9 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20221114150205685.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250210161601541.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250210161601541.png new file mode 100755 index 0000000000000000000000000000000000000000..80845ece8131933a4cd56ae3bd6119c38e0abd26 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250210161601541.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250210170027454.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250210170027454.png new file mode 100755 index 0000000000000000000000000000000000000000..c06081fc2c963af4d1fa8af506804beedefe1b0b Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250210170027454.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250213112932380.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250213112932380.png new file mode 100755 index 0000000000000000000000000000000000000000..8b591b3437544859f4ec76b9ca03867cc401078c Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250213112932380.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919150630870.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919150630870.png new file mode 100755 index 0000000000000000000000000000000000000000..91f881e85b3292118336ce2c3d81968e4aee8c26 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919150630870.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919151018659.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919151018659.png new file mode 100755 index 0000000000000000000000000000000000000000..9b09507893b65d2142be49e6461daa31a81855c4 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919151018659.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919151519310.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919151519310.png new file mode 100755 index 0000000000000000000000000000000000000000..7f6d881a5d0e6d3f72b7a43d089b5c5a75d7f048 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919151519310.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919184816530.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919184816530.png new file mode 100755 index 0000000000000000000000000000000000000000..d9f0932b345fcfa7c140c5f21d352e7e5cff64c4 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919184816530.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919185144994.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919185144994.png new file mode 100755 index 0000000000000000000000000000000000000000..9895a2068cd586218c3a5ff02ec5d78c545ffc1c Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919185144994.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919185208004.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919185208004.png new file mode 100755 index 0000000000000000000000000000000000000000..c29a199bc69ee1234b567cbe69f1a38eec9901d2 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919185208004.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191208927.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191208927.png new file mode 100755 index 0000000000000000000000000000000000000000..3e7e7ce97378be27813af2e1e785abe09c715617 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191208927.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191302486.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191302486.png new file mode 100755 index 0000000000000000000000000000000000000000..ade82dd2219dbaebd70423a330cec800472926f3 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191302486.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191401771.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191401771.png new file mode 100755 index 0000000000000000000000000000000000000000..7cb07614edd60c0e0277898410468468044ef390 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191401771.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191456754.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191456754.png new file mode 100755 index 0000000000000000000000000000000000000000..b564293336921a8118b5df93841f7b0ce0431c41 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919191456754.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192137187.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192137187.png new file mode 100755 index 0000000000000000000000000000000000000000..40ae9c3bd0c0aa31a35641ceb139f98b193505cf Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192137187.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192243361.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192243361.png new file mode 100755 index 0000000000000000000000000000000000000000..a2231c40a1430a678ed005050c743925f2ff02e1 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192243361.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192349341.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192349341.png new file mode 100755 index 0000000000000000000000000000000000000000..e5ba33632d982e6806c584cc20fe487bb61389d6 Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192349341.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192508575.png b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192508575.png new file mode 100755 index 0000000000000000000000000000000000000000..28ee9c1456146bda8ff4119bca992c73bd423b1b Binary files /dev/null and b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/pic/image-20250919192508575.png differ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_kcf_track.c b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_kcf_track.c new file mode 100755 index 0000000000000000000000000000000000000000..45c4fb0b9522c64e816a673792583065597bfa6c --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_kcf_track.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include "ss_mpi_ive.h" +#include "sample_common_svp.h" +#include "sample_common_ive.h" +#include "sample_kcf_track.h" + +#define KCF_QUEUE_LEN 4 /* 简化环形队列深度 */ + +/* **** 新增:KCF 用到的全局结构 **** */ +static sample_yolo_kcf_info g_kcf_info = {0}; /* 资源句柄、互斥锁等 */ +static ot_sample_svp_rect_info g_new_rect; /* NPU 推过来的检测框 */ +static pthread_mutex_t g_rect_mutex = PTHREAD_MUTEX_INITIALIZER; +static td_bool g_has_new_rect = TD_FALSE; /* 标记框是否更新 */ +static td_bool g_stop_flag = TD_FALSE; +static pthread_t g_get_frame_thd = 0; +static pthread_t g_track_thd = 0; +static int g_kcf_mode = 0; // 0=只画红框, 1=跟踪 + +// 新增:全局保存最后有效框和丢失计数(替代线程内的局部静态变量) +static ot_sample_svp_rect_info g_last_valid_rect = {0}; +static td_s32 g_lost_count = 0; + +#define KCF_BOX_WIDTH 200 // 统一宽度 +#define KCF_BOX_HEIGHT 200 // 统一高度 + +static void kcf_rect_to_roi_info(const ot_sample_svp_rect_info *rect, td_u32 base_w, td_u32 base_h) +{ + if (rect->num == 0) { + return; + } + // 只用第0个框,不做任何选择 + g_kcf_info.roi_num = 1; + g_kcf_info.roi_info[0].roi_id = 0; + g_kcf_info.roi_info[0].roi.x = rect->rect[0].point[0].x * OT_SAMPLE_QUARTER_OF_1M; + g_kcf_info.roi_info[0].roi.y = rect->rect[0].point[0].y * OT_SAMPLE_QUARTER_OF_1M; + g_kcf_info.roi_info[0].roi.width = rect->rect[0].point[1].x - rect->rect[0].point[0].x; + g_kcf_info.roi_info[0].roi.height = rect->rect[0].point[2].y - rect->rect[0].point[1].y; /* 2 index */ + // 后续宽高限制代码可保留 + if (g_kcf_info.roi_info[0].roi.width > 684) { /* 684 pic width */ + g_kcf_info.roi_info[0].roi.width = 684; /* 684 pic width */ + } + if (g_kcf_info.roi_info[0].roi.height > 684) { /* 684 pic height */ + g_kcf_info.roi_info[0].roi.height = 684; /* 684 pic height */ + } + if (g_kcf_info.roi_info[0].roi.width < KCF_BOX_WIDTH) { + g_kcf_info.roi_info[0].roi.width = KCF_BOX_WIDTH; + } + if (g_kcf_info.roi_info[0].roi.height < KCF_BOX_HEIGHT) { + g_kcf_info.roi_info[0].roi.height = KCF_BOX_HEIGHT; + } + if ((g_kcf_info.roi_info[0].roi.x / OT_SAMPLE_QUARTER_OF_1M) + g_kcf_info.roi_info[0].roi.width > base_w) { + g_kcf_info.roi_info[0].roi.x = (base_w - g_kcf_info.roi_info[0].roi.width) * OT_SAMPLE_QUARTER_OF_1M; + } + if ((g_kcf_info.roi_info[0].roi.y / OT_SAMPLE_QUARTER_OF_1M) + g_kcf_info.roi_info[0].roi.height > base_h) { + g_kcf_info.roi_info[0].roi.y = (base_h - g_kcf_info.roi_info[0].roi.height) * OT_SAMPLE_QUARTER_OF_1M; + } + if (g_kcf_info.roi_info[0].roi.x < 0) { + g_kcf_info.roi_info[0].roi.x = 0; + } + if (g_kcf_info.roi_info[0].roi.y < 0) { + g_kcf_info.roi_info[0].roi.y = 0; + } + if (g_kcf_info.roi_info[0].roi.width & 1) { + g_kcf_info.roi_info[0].roi.width--; + } + if (g_kcf_info.roi_info[0].roi.height & 1) { + g_kcf_info.roi_info[0].roi.height--; + } +} + +/* **** 简单把 video_frame 填到 ot_svp_img **** */ +static void kcf_fill_image(const ot_video_frame_info *frame, ot_svp_img *img) +{ + img->phys_addr[0] = frame->video_frame.phys_addr[0]; + img->phys_addr[1] = frame->video_frame.phys_addr[1]; + img->stride[0] = frame->video_frame.stride[0]; + img->stride[1] = frame->video_frame.stride[1]; + img->width = frame->video_frame.width; + img->height = frame->video_frame.height; + + /* 根据 VPSS 输出像素格式决定 IVE 输入类型 */ + switch (frame->video_frame.pixel_format) { + case OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420: + case OT_PIXEL_FORMAT_YUV_SEMIPLANAR_420: + img->type = OT_SVP_IMG_TYPE_YUV420SP; + break; + case OT_PIXEL_FORMAT_YVU_SEMIPLANAR_422: + case OT_PIXEL_FORMAT_YUV_SEMIPLANAR_422: + img->type = OT_SVP_IMG_TYPE_YUV422SP; + break; + default: + /* 回退为 420,必要时可扩展 */ + img->type = OT_SVP_IMG_TYPE_YUV420SP; + break; + } +} + +typedef struct { + td_s32 x; + td_s32 y; + td_s32 w; + td_s32 h; +} BoxPosition; + +// 限制框在画面范围内 +static void clamp_box_to_frame(BoxPosition* box, const ot_video_frame_info* frame) +{ + const td_s32 max_w = frame->video_frame.width - 2; /* 2 pixel */ + const td_s32 max_h = frame->video_frame.height - 2; /* 2 pixel */ + + // 确保最小尺寸 + box->w = (box->w > KCF_BOX_WIDTH) ? box->w : KCF_BOX_WIDTH; + box->h = (box->h > KCF_BOX_HEIGHT) ? box->h : KCF_BOX_HEIGHT; + + /* 4 允许超出的最大范围(框宽的1/4) */ + const td_s32 max_overlap = box->w / 4; + if (box->x + box->w > max_w + max_overlap) { + box->x = max_w - box->w; + } + if (box->y + box->h > max_h + max_overlap) { + box->y = max_h - box->h; + } +} + +// 消除位置抖动 +static void smooth_box_position(BoxPosition* current, BoxPosition* last, td_bool* is_first_frame) +{ + if (*is_first_frame) { + *last = *current; + *is_first_frame = TD_FALSE; + return; + } + + // 微小变化时保持上一帧位置 + if (abs(current->x - last->x) <= 2 && abs(current->y - last->y) <= 2 && /* 2 pixel */ + abs(current->w - last->w) <= 2 && abs(current->h - last->h) <= 2) { /* 2 pixel */ + *current = *last; + } else { + *last = *current; + } +} + +// 确保坐标和尺寸为偶数 +static void align_to_even(BoxPosition* box) +{ + box->x &= ~1; // 清除最低位保证为偶数 + box->y &= ~1; + box->w &= ~1; + box->h &= ~1; +} + +// 设置矩形顶点坐标 +static void set_rect_points(ot_sample_svp_rect* rect, const BoxPosition* box) +{ + rect->point[0].x = box->x; + rect->point[0].y = box->y; + rect->point[1].x = box->x + box->w; + rect->point[1].y = box->y; + rect->point[2].x = box->x + box->w; /* 2 index of 2 */ + rect->point[2].y = box->y + box->h; /* 2 index of 2 */ + rect->point[3].x = box->x; /* 3 index of 3 */ + rect->point[3].y = box->y + box->h; /* 3 index of 3 */ +} + +static void kcf_bbox_to_rect(const ot_ive_kcf_bbox bbox[], td_u32 num, + const ot_video_frame_info* frame, ot_sample_svp_rect_info* rect) +{ + rect->num = (num > 0) ? 1 : 0; + if (rect->num == 0) { + return; + } + // 初始化转换参数 + static BoxPosition last_box = {0}; + static td_bool first_frame = TD_TRUE; + + BoxPosition current = { + .x = bbox[0].roi_info.roi.x / OT_SAMPLE_QUARTER_OF_1M, + .y = bbox[0].roi_info.roi.y / OT_SAMPLE_QUARTER_OF_1M, + .w = bbox[0].roi_info.roi.width, + .h = bbox[0].roi_info.roi.height + }; + + // 处理流程 + clamp_box_to_frame(¤t, frame); + smooth_box_position(¤t, &last_box, &first_frame); + align_to_even(¤t); + + // 设置输出矩形 + set_rect_points(&rect->rect[0], ¤t); +} +/* 边界检测辅助函数 */ +static td_bool is_touching_border(const ot_sample_svp_rect *rect, td_s32 screen_w, + td_s32 screen_h, td_s32 threshold) +{ + td_s32 rect_left = rect->point[0].x; + td_s32 rect_top = rect->point[0].y; + td_s32 rect_right = rect->point[1].x; + td_s32 rect_bottom = rect->point[2].y; + + return (rect_left <= threshold) || (rect_top <= threshold) || + ((screen_w - rect_right) <= threshold) || ((screen_h - rect_bottom) <= threshold); +} + +/* 绘制矩形辅助函数 */ +static void draw_tracking_rect(const ot_video_frame_info *frm, + const ot_sample_svp_rect_info *rect_info, td_bool is_touching_border) +{ + td_u32 color = is_touching_border ? 0x00FFFF00 : 0x0000FF00; + sample_common_svp_vgs_fill_rect(frm, rect_info, color); +} + +/* KCF训练辅助函数 */ +static void train_kcf_on_new_rect(const ot_video_frame_info *frm) +{ + pthread_mutex_lock(&g_rect_mutex); + kcf_rect_to_roi_info(&g_new_rect, frm->video_frame.width, frm->video_frame.height); + g_has_new_rect = TD_FALSE; + pthread_mutex_unlock(&g_rect_mutex); + + td_s32 ret = ss_mpi_ive_kcf_get_train_obj( + g_kcf_info.padding, g_kcf_info.roi_info, + g_kcf_info.roi_num, &g_kcf_info.cos_win_x, + &g_kcf_info.cos_win_y, &g_kcf_info.gauss_peak, + &g_kcf_info.obj_list); + if (ret != TD_SUCCESS) { + printf("[KCF] get_train_obj failed 0x%x, w=%u h=%u\n", ret, + g_kcf_info.roi_info[0].roi.width, + g_kcf_info.roi_info[0].roi.height); + } else { + printf("[KCF] train_obj_num=%u\n", g_kcf_info.obj_list.train_obj_num); + } +} + +/* 处理丢失目标情况 */ +static void handle_lost_target(const ot_video_frame_info *frm) +{ + g_lost_count++; + printf("[KCF] Lost target (count=%d), keep last rect\n", g_lost_count); + + if (g_last_valid_rect.num > 0) { + sample_common_svp_vgs_fill_rect(frm, &g_last_valid_rect, 0x00FFFF00); + } + + if (g_lost_count >= 10 && g_last_valid_rect.num > 0) { /* 10 lost count */ + pthread_mutex_lock(&g_rect_mutex); + g_new_rect = g_last_valid_rect; + g_has_new_rect = TD_TRUE; + pthread_mutex_unlock(&g_rect_mutex); + g_lost_count = 0; + } +} + +static void process_kcf_tracking(const ot_video_frame_info* frm, + ot_sample_svp_rect_info* draw_rect) +{ + td_s32 ret; + ot_ive_handle handle = 0; + ot_svp_img src_img; + + // 填充图像数据 + kcf_fill_image(frm, &src_img); + + // 执行KCF处理 + ret = ss_mpi_ive_kcf_proc(&handle, &src_img, &g_kcf_info.obj_list, + &g_kcf_info.kcf_proc_ctrl, TD_TRUE); + if (ret != TD_SUCCESS) { + printf("[KCF] kcf_proc failed 0x%x\n", ret); + g_kcf_info.bbox_obj_num = 0; + return; + } + + // 获取目标边界框 + ret = ss_mpi_ive_kcf_get_obj_bbox(&g_kcf_info.obj_list, g_kcf_info.bbox, + &g_kcf_info.bbox_obj_num, &g_kcf_info.kcf_bbox_ctrl); + if (ret != TD_SUCCESS) { + printf("[KCF] get_obj_bbox failed 0x%x\n", ret); + g_kcf_info.bbox_obj_num = 0; + return; + } + + // 处理有效目标 + if (g_kcf_info.bbox_obj_num > 0) { + kcf_bbox_to_rect(g_kcf_info.bbox, g_kcf_info.bbox_obj_num, frm, draw_rect); + + td_s32 screen_w = frm->video_frame.width - 2; + td_s32 screen_h = frm->video_frame.height - 2; + td_bool touching_border = is_touching_border( + &draw_rect->rect[0], screen_w, screen_h, 5); + + draw_tracking_rect(frm, draw_rect, touching_border); + g_last_valid_rect = *draw_rect; + g_lost_count = 0; + } +} + +/* 主线程函数(重构后) */ +static void *kcf_track_thread(void *args) +{ + (void)args; + td_s32 ret; + const ot_vo_layer vo_layer = 0; + const ot_vo_chn vo_chn = 0; + const td_s32 milli_sec = 20; + const td_s32 vpss_grp = 0; + const td_s32 vpss_chn = 0; + ot_sample_svp_rect_info draw_rect = {0}; + + while (!g_stop_flag) { + ot_video_frame_info frm; + ret = ss_mpi_vpss_get_chn_frame(vpss_grp, vpss_chn, &frm, milli_sec); + if (ret != TD_SUCCESS) { + usleep(1000); // 1000 sleep 1ms + continue; + } + + // 红框模式处理 + if (g_kcf_mode == 0) { + ot_ive_kcf_bbox initial_bbox[1]; + initial_bbox[0].roi_info = g_kcf_info.roi_info[0]; + kcf_bbox_to_rect(initial_bbox, 1, &frm, &draw_rect); + sample_common_svp_vgs_fill_rect(&frm, &draw_rect, 0x00FF0000); + g_kcf_info.bbox_obj_num = 0; + goto send_and_release; + } + + // 训练模式处理 + if (g_has_new_rect) { + train_kcf_on_new_rect(&frm); + } + + // 跟踪模式处理 + if (g_kcf_mode == 1 && (g_kcf_info.obj_list.train_obj_num != 0 || + g_kcf_info.obj_list.track_obj_num != 0)) { + process_kcf_tracking(&frm, &draw_rect); + } else if (g_kcf_mode == 1) { + g_kcf_info.bbox_obj_num = 0; + } + // 处理丢失目标 + if (g_kcf_mode == 1 && g_kcf_info.bbox_obj_num == 0) { + handle_lost_target(&frm); + } + + send_and_release: + ret = sample_common_svp_venc_vo_send_stream(&g_kcf_info.svp_switch, 0, + vo_layer, vo_chn, &frm); + if (ret != TD_SUCCESS) { + printf("[KCF] sample_common_svp_venc_vo_send_stream failed 0x%x\n", ret); + } + (td_void)ss_mpi_vpss_release_chn_frame(vpss_grp, vpss_chn, &frm); + usleep(8000); // 8000 sleep 8ms + } + return TD_NULL; +} + +static void sample_kcf_info_init(ot_svp_mem_info total_mem, td_u32 list_mem_size) +{ + g_kcf_info.list_mem = total_mem; + g_kcf_info.list_mem.size = list_mem_size; + + g_kcf_info.gauss_peak.phys_addr = g_kcf_info.list_mem.phys_addr + list_mem_size; + g_kcf_info.gauss_peak.virt_addr = g_kcf_info.list_mem.virt_addr + list_mem_size; + g_kcf_info.gauss_peak.size = SAMPLE_KCF_GAUSS_PEAK_SIZE; + + g_kcf_info.cos_win_x.phys_addr = g_kcf_info.gauss_peak.phys_addr + SAMPLE_KCF_GAUSS_PEAK_SIZE; + g_kcf_info.cos_win_x.virt_addr = g_kcf_info.gauss_peak.virt_addr + SAMPLE_KCF_GAUSS_PEAK_SIZE; + g_kcf_info.cos_win_x.size = SAMPLE_KCF_COS_WIN_SIZE; + + g_kcf_info.cos_win_y.phys_addr = g_kcf_info.cos_win_x.phys_addr + SAMPLE_KCF_COS_WIN_SIZE; + g_kcf_info.cos_win_y.virt_addr = g_kcf_info.cos_win_x.virt_addr + SAMPLE_KCF_COS_WIN_SIZE; + g_kcf_info.cos_win_y.size = SAMPLE_KCF_COS_WIN_SIZE; + + g_kcf_info.kcf_proc_ctrl.tmp_buf.phys_addr = + g_kcf_info.cos_win_y.phys_addr + SAMPLE_KCF_COS_WIN_SIZE; + g_kcf_info.kcf_proc_ctrl.tmp_buf.virt_addr = + g_kcf_info.cos_win_y.virt_addr + SAMPLE_KCF_COS_WIN_SIZE; + g_kcf_info.kcf_proc_ctrl.tmp_buf.size = SAMPLE_KCF_TEMP_BUF_SIZE; +} + +static void sample_kcf_proc_ctrl_init(void) +{ + g_kcf_info.kcf_proc_ctrl.csc_mode = OT_IVE_CSC_MODE_VIDEO_BT709_YUV_TO_RGB; + /* 0.001 learning rate 1024 Quantization scaling factor 32 Additional scaling factor */ + g_kcf_info.kcf_proc_ctrl.interp_factor = (td_u1q15)(0.001 * 1024 * 32); /* 降低学习率,减少抖动 ≈327 */ + g_kcf_info.kcf_proc_ctrl.lamda = 10; /* 10 lamda */ + g_kcf_info.kcf_proc_ctrl.sigma = (td_u0q8)(0.5 * 256); /* 0.5 * 256 降低sigma,提高稳定性 ≈77 */ + g_kcf_info.kcf_proc_ctrl.norm_trunc_alfa = (td_u4q12)(0.15 * 4096); /* 0.15 * 4096 降低截断因子 ≈614 */ + g_kcf_info.kcf_proc_ctrl.response_threshold = 5; /* 5 提高阈值,减少误检 */ + g_kcf_info.kcf_proc_ctrl.core_id = OT_IVE_KCF_CORE0; +} + +static void sample_kcf_bbox_ctrl_init(void) +{ + g_kcf_info.kcf_bbox_ctrl.max_bbox_num = SAMPLE_KCF_LIST_NODE_MAX; + g_kcf_info.kcf_bbox_ctrl.response_threshold = 12; /* 12 threshold */ + g_kcf_info.padding = 48; /* 48 padding */ +} + +static td_s32 sample_kcf_media_cfg(const ot_sample_svp_media_cfg *media_cfg) +{ + if (media_cfg != TD_NULL) { + g_kcf_info.svp_switch = media_cfg->svp_switch; /* {TD_FALSE, TD_TRUE} */ + } else { + g_kcf_info.svp_switch.is_venc_open = TD_FALSE; + g_kcf_info.svp_switch.is_vo_open = TD_TRUE; + } + + g_stop_flag = TD_FALSE; + // Removed g_get_frame_thd creation + if (pthread_create(&g_track_thd, NULL, kcf_track_thread, NULL) != 0) { + return TD_FAILURE; + } + // 在 sample_kcf_track_init 末尾添加 + g_kcf_info.roi_num = 1; + g_kcf_info.roi_info[0].roi_id = 0; + td_u32 safe_margin = 50; /* 50 Edge safety distance */ + td_u32 init_x = (1920 - KCF_BOX_WIDTH) / 2; /* 1920 PIC of width */ + td_u32 init_y = (1080 - KCF_BOX_HEIGHT) / 2; /* 1080 PIC of width */ + // 确保初始位置不靠近边缘(至少50像素缓冲) + if (init_x < safe_margin) init_x = safe_margin; + if (init_y < safe_margin) init_y = safe_margin; + g_kcf_info.roi_info[0].roi.x = init_x * OT_SAMPLE_QUARTER_OF_1M; + g_kcf_info.roi_info[0].roi.y = init_y * OT_SAMPLE_QUARTER_OF_1M; + g_kcf_info.roi_info[0].roi.width = KCF_BOX_WIDTH; + g_kcf_info.roi_info[0].roi.height = KCF_BOX_HEIGHT; + + return TD_SUCCESS; +} + +td_s32 sample_kcf_track_init(const ot_sample_svp_media_cfg *media_cfg, sample_vo_cfg *vo_cfg) +{ + memset(&g_kcf_info, 0, sizeof(g_kcf_info)); + pthread_mutex_init(&g_kcf_info.det_mutex, NULL); + + /* ---------------- KCF 内存初始化 ---------------- */ + td_s32 ret; + td_u32 list_mem_size; + td_u32 total_size; + + /* 1. 计算对象链表大小 */ + ret = ss_mpi_ive_kcf_get_mem_size(SAMPLE_KCF_LIST_NODE_MAX, &list_mem_size); + if (ret != TD_SUCCESS) { + printf("kcf get mem size failed 0x%x\n", ret); + return ret; + } + + /* 2. 申请一整块连续内存 (list + gauss + cosX + cosY + tmp) */ + total_size = list_mem_size + SAMPLE_KCF_GAUSS_PEAK_SIZE + + SAMPLE_KCF_COS_WIN_SIZE * 2 + SAMPLE_KCF_TEMP_BUF_SIZE; /* 2 is a number */ + + ot_svp_mem_info total_mem = {0}; + ret = sample_common_ive_create_mem_info(&total_mem, total_size); + if (ret != TD_SUCCESS) { + printf("kcf alloc total mem failed 0x%x\n", ret); + return ret; + } + + /* 3. 切分子区域 */ + sample_kcf_info_init(total_mem, list_mem_size); + + /* 4. 创建对象链表 */ + ret = ss_mpi_ive_kcf_create_obj_list(&g_kcf_info.list_mem, SAMPLE_KCF_LIST_NODE_MAX, &g_kcf_info.obj_list); + if (ret != TD_SUCCESS) { + printf("create obj list err 0x%x\n", ret); + return ret; + } + + /* 5. 生成 GaussPeak / CosWin 窗口 */ + g_kcf_info.padding = 48; /* 48 is 1.5*32 */ + ret = ss_mpi_ive_kcf_create_gauss_peak(g_kcf_info.padding, &g_kcf_info.gauss_peak); + if (ret != TD_SUCCESS) { + printf("create gauss peak err 0x%x\n", ret); + return ret; + } + ret = ss_mpi_ive_kcf_create_cos_win(&g_kcf_info.cos_win_x, &g_kcf_info.cos_win_y); + if (ret != TD_SUCCESS) { + printf("create cos win err 0x%x\n", ret); + return ret; + } + + /* 6. 填写 kcf_proc_ctrl 默认参数 */ + sample_kcf_proc_ctrl_init(); + + /* 7. 初始化 bbox ctrl */ + sample_kcf_bbox_ctrl_init(); + + /* 8. 继承媒体配置中的开关,使 KCF 线程能够把结果帧送到 VO/VENC */ + ret = sample_kcf_media_cfg(media_cfg); + if (ret != TD_SUCCESS) { + printf("kcf media cfg err 0x%x\n", ret); + return ret; + } + + return TD_SUCCESS; +} + +void sample_kcf_track_deinit(void) +{ + g_stop_flag = TD_TRUE; + // Removed g_get_frame_thd join + if (g_track_thd) { + pthread_join(g_track_thd, NULL); + } + /* 释放 KCF 内存与对象链表 */ + ss_mpi_ive_kcf_destroy_obj_list(&g_kcf_info.obj_list); + + /* 仅需释放一次整块内存,避免重复 free 导致 mmb not found 警告 */ + sample_svp_mmz_free(g_kcf_info.list_mem.phys_addr, g_kcf_info.list_mem.virt_addr); + + pthread_mutex_destroy(&g_kcf_info.det_mutex); +} + +// 修改 sample_kcf_set_det_rect,只在切换到跟踪模式时设置 g_has_new_rect +void sample_kcf_set_det_rect(const ot_sample_svp_rect_info *rect, int mode) +{ + pthread_mutex_lock(&g_rect_mutex); + g_new_rect = *rect; + if (mode == 1) { + ss_mpi_ive_kcf_destroy_obj_list(&g_kcf_info.obj_list); + ss_mpi_ive_kcf_create_obj_list(&g_kcf_info.list_mem, SAMPLE_KCF_LIST_NODE_MAX, &g_kcf_info.obj_list); + g_has_new_rect = TD_TRUE; + // 重置上一次的黄色框信息,避免切换时残留 + memset(&g_last_valid_rect, 0, sizeof(ot_sample_svp_rect_info)); + g_lost_count = 0; + } else if (mode == 0) { // 切换到红色框模式:强制红框回到中央 + // 计算屏幕中央坐标(基于1920x1080分辨率) + td_u32 center_x = (1920 - KCF_BOX_WIDTH) / 2; // 中央x坐标 + td_u32 center_y = (1080 - KCF_BOX_HEIGHT) / 2; // 中央y坐标 + // 重置红框的初始位置到中央(与初始化时一致) + g_kcf_info.roi_info[0].roi.x = center_x * OT_SAMPLE_QUARTER_OF_1M; + g_kcf_info.roi_info[0].roi.y = center_y * OT_SAMPLE_QUARTER_OF_1M; + // 保持宽高不变(KCF_BOX_WIDTH x KCF_BOX_HEIGHT) + g_kcf_info.roi_info[0].roi.width = KCF_BOX_WIDTH; + g_kcf_info.roi_info[0].roi.height = KCF_BOX_HEIGHT; + } + g_kcf_mode = mode; + + if (mode == 0) { + g_kcf_info.obj_list.train_obj_num = 0; + g_kcf_info.obj_list.track_obj_num = 0; + g_kcf_info.bbox_obj_num = 0; + } + pthread_mutex_unlock(&g_rect_mutex); +} + +td_u32 sample_kcf_get_bbox_num(void) +{ + return g_kcf_info.bbox_obj_num; +} diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_kcf_track.h b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_kcf_track.h new file mode 100755 index 0000000000000000000000000000000000000000..9b5a4d2111c76506641612fdc6db91b31c2095ff --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_kcf_track.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SAMPLE_KCF_TRACK_H +#define SAMPLE_KCF_TRACK_H + +#include +#include "sample_comm.h" +#include "ot_common_svp.h" +#include "sample_common_svp.h" +#include "sample_common_ive.h" + +#ifndef SAMPLE_YOLO_KCF_INFO_T +#define SAMPLE_YOLO_KCF_INFO_T +#define SAMPLE_KCF_MAX_OBJ 4 + +typedef struct { + ot_ive_roi_info roi_info[SAMPLE_KCF_MAX_OBJ]; + td_u32 roi_num; + + /* 训练相关内存 */ + ot_svp_mem_info cos_win_x; + ot_svp_mem_info cos_win_y; + ot_svp_mem_info gauss_peak; + ot_svp_mem_info list_mem; /* KCF 对象链表内存 */ + ot_ive_kcf_obj_list obj_list; + ot_ive_kcf_proc_ctrl kcf_proc_ctrl; + ot_ive_kcf_bbox_ctrl kcf_bbox_ctrl; + + /* 跟踪结果 */ + ot_ive_kcf_bbox bbox[SAMPLE_KCF_MAX_OBJ]; + td_u32 bbox_obj_num; + + /* 帧缓存 */ + ot_video_frame_info frame_info_arr[1]; + + /* 互斥 */ + pthread_mutex_t det_mutex; + + /* 其它 */ + td_u3q5 padding; /* 调 API 需要的 padding 值 */ + ot_sample_svp_switch svp_switch; + sample_vo_cfg vo_cfg; /* VO configuration */ +} sample_yolo_kcf_info; +#endif + +#define SAMPLE_KCF_LIST_NODE_MAX 64 +#define SAMPLE_KCF_GAUSS_PEAK_SIZE 455680 +#define SAMPLE_KCF_COS_WIN_SIZE 832 +#define SAMPLE_KCF_TEMP_BUF_SIZE 47616 + +/* 说明: + * 1. sample_kcf_track_init 内部会创建获取帧+跟踪线程并一直运行; + * 2. 检测线程(NPU/RFCN 或 YOLO)每获得一次新检测框,调用 sample_kcf_set_det_rect + * 把第一只目标的 rect 信息推送给 KCF,KCF 会在下一帧里自动训练 / 跟踪; + * 3. sample_kcf_track_deinit 会安全地结束线程并释放内存。 + */ +td_s32 sample_kcf_track_init(const ot_sample_svp_media_cfg *media_cfg, sample_vo_cfg *vo_cfg); +void sample_kcf_track_deinit(void); + +void sample_kcf_set_det_rect(const ot_sample_svp_rect_info *rect, int mode); + +td_u32 sample_kcf_get_bbox_num(void); + +#endif /* SAMPLE_KCF_TRACK_H */ diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_svp_npu_process.c b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_svp_npu_process.c new file mode 100755 index 0000000000000000000000000000000000000000..5f655d4a9d87cf8e6e821188b665269feedc08ec --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_svp_npu_process.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include "sample_comm.h" +#include "sample_common_svp.h" +#include "sample_common_svp_npu.h" +#include "sample_common_svp_npu_model.h" +#include "sample_kcf_track.h" +#include "sample_svp_npu_process.h" + +#ifndef OT_SAMPLE_SYS_ALIGN_SIZE +#define OT_SAMPLE_SYS_ALIGN_SIZE 64 // 常见对齐值,根据 SDK 调整 +#endif +#ifndef CIF_WIDTH +#define CIF_WIDTH 200 +#endif +#ifndef CIF_HEIGHT +#define CIF_HEIGHT 200 +#endif + +// getch实现放在文件顶部 +static int getch(void) +{ + struct termios oldt; + struct termios newt; + int ch; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + ch = getchar(); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return ch; +} + +td_s32 sample_common_svp_get_def_vo_cfg(sample_vo_cfg *vo_cfg); +static td_bool g_svp_npu_terminate_signal = TD_FALSE; +static sample_vi_cfg g_vi_config; + +static ot_sample_svp_rect_info g_svp_npu_rect_info = {0}; +static td_bool g_svp_npu_thread_stop = TD_FALSE; +static pthread_t g_svp_npu_thread = 0; +static sample_vo_cfg g_svp_npu_vo_cfg = { 0 }; +static pthread_t g_svp_npu_vdec_thread = 0; +static ot_vb_pool_info g_svp_npu_vb_pool_info; +static td_void *g_svp_npu_vb_virt_addr = TD_NULL; + +static ot_sample_svp_media_cfg g_svp_npu_media_cfg = { + .svp_switch = {TD_FALSE, TD_TRUE}, + .pic_type = {PIC_1080P, PIC_CIF}, // Changed to PIC_1080P for main stream + .chn_num = OT_SVP_MAX_VPSS_CHN_NUM, +}; + +static sample_vdec_attr g_svp_npu_vdec_cfg = { + .type = OT_PT_MJPEG, + .mode = OT_VDEC_SEND_MODE_FRAME, + .width = FHD_WIDTH, // Changed to FHD_WIDTH + .height = FHD_HEIGHT, // Changed to FHD_HEIGHT + .sample_vdec_picture.pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420, /* 420:pixel_format */ + .sample_vdec_picture.alpha = 0, /* 0:alpha */ + .display_frame_num = 1, /* Keep 1 */ + .frame_buf_cnt = 3, /* Keep 3 */ +}; + +static vdec_thread_param g_svp_npu_vdec_param = { + .chn_id = 0, + + .v4l2_device = "/dev/video0", // 摄像头设备 + .width = FHD_WIDTH, // Changed to FHD_WIDTH + .height = FHD_HEIGHT, // Changed to FHD_HEIGHT + .pixel_format = V4L2_PIX_FMT_MJPEG, // MJPEG格式 + + .type = OT_PT_MJPEG, + .stream_mode = OT_VDEC_SEND_MODE_FRAME, + .interval_time = 1000, /* 1000:interval_time */ + .pts_init = 0, + .pts_increase = 0, + .e_thread_ctrl = THREAD_CTRL_START, + .circle_send = TD_TRUE, + .milli_sec = 0, + .min_buf_size = (FHD_WIDTH * FHD_HEIGHT * 3) >> 1, /* 3 Re-calculated for 1080P */ + .fps = 30, /* 30 fps */ +}; + +td_void sample_vb_cfg_init(ot_vb_cfg *vb_cfg, ot_size size_1080p, ot_size size_cif) +{ + td_u64 raw_size_1080p = 0; + td_u64 raw_size_cif = 0; + + raw_size_1080p = (td_u64)size_1080p.width * size_1080p.height * 3 / 2; /* 3 2 YUV420: 1.5 bytes per pixel */ + vb_cfg->max_pool_cnt = 2; /* 2 pool */ + vb_cfg->common_pool[0].blk_size = (raw_size_1080p + OT_SAMPLE_SYS_ALIGN_SIZE - 1) & ~(OT_SAMPLE_SYS_ALIGN_SIZE - 1); + vb_cfg->common_pool[0].blk_cnt = 10; // 块数,根据需要调整(对于1080P,建议10-20) + + raw_size_cif = (td_u64)size_cif.width * size_cif.height * 3 / 2; /* 3 2 raw size */ + vb_cfg->common_pool[1].blk_size = (raw_size_cif + OT_SAMPLE_SYS_ALIGN_SIZE - 1) & ~(OT_SAMPLE_SYS_ALIGN_SIZE - 1); + vb_cfg->common_pool[1].blk_cnt = 4; /* 4 pool */ +} + +td_void sample_center_rect_init(ot_sample_svp_rect_info *center_rect) +{ + int frame_w = FHD_WIDTH; + int frame_h = FHD_HEIGHT; // Use FHD resolution for initial box + int box_w = CIF_WIDTH; + int box_h = CIF_HEIGHT; // A reasonable box size for FHD + int x = (frame_w - box_w) / 2; /* 2 half of x */ + int y = (frame_h - box_h) / 2; /* 2 half of y */ + + center_rect->num = 1; + center_rect->rect[0].point[0].x = x; + center_rect->rect[0].point[0].y = y; + center_rect->rect[0].point[1].x = x + box_w; + center_rect->rect[0].point[1].y = y; + center_rect->rect[0].point[2].x = x + box_w; /* 2 index of 2 */ + center_rect->rect[0].point[2].y = y + box_h; /* 2 index of 2 */ + center_rect->rect[0].point[3].x = x; /* 3 index of 3 */ + center_rect->rect[0].point[3].y = y + box_h; /* 3 index of 3 */ + + printf("[MAIN-2] Setting input rect: (%d,%d) to (%d,%d)\n", + center_rect->rect[0].point[0].x, center_rect->rect[0].point[0].y, + center_rect->rect[0].point[2].x, center_rect->rect[0].point[2].y); /* 2 index of 2 */ +} + +// 1. 程序启动时,推送中心红框,KCF只画红框不训练 +static td_void sample_svp_npu_kcf_tracking_loop(td_void) +{ + ot_sample_svp_rect_info center_rect = {0}; + sample_center_rect_init(¢er_rect); + sample_kcf_set_det_rect(¢er_rect, 0); // 0=只画红框 + + int tracking_on = 0; // 0=红框, 1=跟踪 + // FIX: Use non-blocking input check to avoid blocking termination signal + struct termios oldt; + struct termios newt; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + + while (!g_svp_npu_terminate_signal) { + int ch = getch(); + if (ch == ' ') { + tracking_on = !tracking_on; // 切换模式 + if (tracking_on) { + sample_kcf_set_det_rect(¢er_rect, 1); // 进入跟踪模式,重新训练KCF + printf("[MAIN] Set to tracking mode\n"); + } else { + sample_kcf_set_det_rect(¢er_rect, 0); // 回到红框模式 + printf("[MAIN] Set to red box mode\n"); + } + } else if (ch == 'q') { + break; + } + usleep(100000); // 100000 100ms poll to reduce CPU usage + } + // Restore terminal settings + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); +} + +td_void sample_svp_npu_acl_v4l2_kcf(td_void) +{ + td_s32 ret; + ot_vb_cfg vb_cfg = {0}; + ot_size size_cif; + ot_size size_1080p; + + g_svp_npu_terminate_signal = TD_FALSE; /* 清除退出标志 */ + // 计算 1080P 的 blk_size + sample_comm_sys_get_pic_size(PIC_1080P, &size_1080p); // 从 SDK 获取标准分辨率 (1920x1080) + // 计算 CIF 的 blk_size + sample_comm_sys_get_pic_size(PIC_CIF, &size_cif); // 从 SDK 获取标准分辨率 (352x288) + sample_vb_cfg_init(&vb_cfg, size_1080p, size_cif); + ret = sample_comm_sys_init(&vb_cfg); // 初始化系统 VB + if (ret != TD_SUCCESS) { + printf("[SYS] init failed 0x%x\n", ret); + return; + } + /* ** 2. 新增:获取默认VO配置 ** */ + ret = sample_common_svp_get_def_vo_cfg(&g_svp_npu_vo_cfg); + if (ret != TD_SUCCESS) { + printf("[VO] get default config failed 0x%x\n", ret); + sample_comm_sys_exit(); // **** 新增:清理系统 VB **** + return; + } + /* 3. 根据采集分辨率重新设定 VB 图像类型,避免无谓的 4K 内存开销 */ + g_svp_npu_media_cfg.pic_type[0] = PIC_1080P; + g_svp_npu_media_cfg.pic_type[1] = PIC_CIF; /* 备用,不使用 */ + + /* 4. 启动 V4L2->VDEC->VPSS->VO 通路(内部自动绑定) */ + ret = sample_common_svp_create_vb_start_vdec_vpss_vo(&g_svp_npu_vdec_cfg, &g_svp_npu_vdec_param, + &g_svp_npu_vdec_thread, &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); + if (ret != TD_SUCCESS) { + printf("[PIPE] create pipeline failed 0x%x\n", ret); + sample_common_svp_destroy_vb_stop_vdec_vpss_vo(&g_svp_npu_vdec_param, &g_svp_npu_vdec_thread, + &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); + return; + } + /* 4. 启动 KCF 跟踪——内部线程会从 VPSS grp0 chn0 拉帧并画框 */ + ret = sample_kcf_track_init(&g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); + if (ret != TD_SUCCESS) { + printf("[KCF] init failed 0x%x\n", ret); + sample_common_svp_destroy_vb_stop_vdec_vpss_vo(&g_svp_npu_vdec_param, &g_svp_npu_vdec_thread, + &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); + return; + } + + sample_svp_npu_kcf_tracking_loop(); + + sample_kcf_track_deinit(); + sample_common_svp_destroy_vb_stop_vdec_vpss_vo(&g_svp_npu_vdec_param, &g_svp_npu_vdec_thread, + &g_svp_npu_media_cfg, &g_svp_npu_vo_cfg); + sample_comm_sys_exit(); +} diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_svp_npu_process.h b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_svp_npu_process.h new file mode 100755 index 0000000000000000000000000000000000000000..09ccdb7b41a19ea2af9fc8b9f25e4184ca12d6e0 --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sample_kcf_track/sample_svp_npu_process.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 HiSilicon (Shanghai) Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLE_SVP_NPU_PROCESS_H +#define SAMPLE_SVP_NPU_PROCESS_H +#include "ot_type.h" + +/* function : show the sample of v4l2 -> VDEC -> VPSS -> KCF -> VGS/VO */ +td_void sample_svp_npu_acl_v4l2_kcf(td_void); + +#endif diff --git a/vendor/ZhongShanKuangShi_CUST/demo/sdk_linux.mk b/vendor/ZhongShanKuangShi_CUST/demo/sdk_linux.mk new file mode 100755 index 0000000000000000000000000000000000000000..ae4dc7394bcf98706ce3c2d9a9e1ebcb48e8d15c --- /dev/null +++ b/vendor/ZhongShanKuangShi_CUST/demo/sdk_linux.mk @@ -0,0 +1,93 @@ +#==================================================== +# SDK libs +#==================================================== +MPI_LIBS += -L$(TARGET_DIR) +MPI_LIBS += -L$(SDK_LINUX_OUT_LIB) +MPI_LIBS += -L$(SYSROOT_PATH)/lib +#MPI_LIBS += -L$(SYSROOT_PATH)/usr/lib +#MPI_LIBS += -L$(OUT_UNSTRIPPED_LIB) +MPI_LIBS += -lot_osal -lot_base -lot_sys -lot_chnl -lot_rgn -lot_vpp -lot_vo -lot_vgs -lot_vpss -lsecurec +MPI_LIBS += -lot_vdec -lot_h265e -lot_h264e -lot_jpege -lot_venc -lot_vedu -lot_vi -lot_mpi_isp -lot_rc -lot_jpegd +MPI_LIBS += -lot_sensor_i2c -lot_sensor_spi -lot_aio -lot_ai -lot_ao -lot_aenc -lot_adec -lot_acodec -lot_irq +MPI_LIBS += -lss_mpi -lss_mau -lss_dpu_match -lss_ive -lss_dpu_rect -lss_pqp -lss_hdmi -lot_vfmw -lot_isp -lot_dis +MPI_LIBS += -lot_gdc -lss_ae -lss_isp -lot_isp -lss_awb -lss_dehaze -lss_extend_stats -lss_drc -lss_ldci -lss_crb -lss_bnr -lss_voice_engine -lss_upvqe -lss_dnvqe +MPI_LIBS += -lss_calcflicker -lss_ir_auto -lss_acs -lss_acs -lsns_hy_s0603 +#MPI_LIBS += -lsns_os08a20 -lsns_os05a10_2l_slave -lsns_imx347_slave -lsns_imx485 -lsns_os04a10 -lsns_os08b10 +MPI_LIBS += $(SDK_LINUX_OUT_LIB)/svp_npu/libsvp_acl.a +MPI_LIBS += -L$(SDK_LINUX_OUT_LIB)/svp_npu -lprotobuf-c + +# 设置浮点运算, cpu类型, 链接器的相关设置 +CFLAGS += -Dss928v100 -DOT_XXXX -lpthread -lm -ldl -DISP_V2 -lc++ -lc -Wall -fsigned-char -mcpu=cortex-a53 -ldl -ffunction-sections -fdata-sections -O2 -fstack-protector-strong -fPIC -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -fPIE -pie -s -Wall -fsigned-char -DOT_RELEASE -DVER_X=1 -DVER_Y=0 -DVER_Z=0 -DVER_P=0 -DVER_B=10 -DUSER_BIT_64 -DKERNEL_BIT_64 -Wno-date-time + +#==================================================== +# SDK include +#==================================================== +CFLAGS += -I$(SDK_LINUX_INCLUDE_DIR) +#CFLAGS += -I$(BOUNDS_CHECKING_DIR) +CFLAGS += -I$(SDK_SAMPLE_COMMON_DIR) +CFLAGS += -I$(SVP_COMMON_DIR) + +#==================================================== +# Source FileList +#==================================================== +SOURCE_TREE := $(ROOT_DIR) +BUILD_TREE := $(ROOT_DIR) + +#==================================================== +# Objects FileList +#==================================================== +SRC_ROOT := $(SOURCE_TREE) +OBJ_ROOT := $(OBJS_DIR) +OBJS := $(SMP_SRCS:$(SRC_ROOT)%.c=$(OBJ_ROOT)%.o) +OBJS := $(sort $(OBJS)) +OBJS_DIR := $(sort $(dir $(OBJS))) +CPP_OBJS := $(CPP_SRCS:$(SRC_ROOT)%.cpp=$(OBJ_ROOT)%.o) +OBJS_DIR += $(sort $(dir $(CPP_OBJS))) + +#==================================================== +# Create Directory +#==================================================== +CreateDir = $(shell [ -d $1 ] || mkdir -p $1 || echo ":mkdir '$1' fail") +CreateResult := +dummy := $(call CreateDir, $(OBJS_ROOT)) +dummy += $(foreach dir, $(OBJS_DIR), CreateResult += $(call CreateDir, $(dir))) +ifneq ($(strip CreateDir),) + err = $(error $(CreateResult)) +endif + +#==================================================== +# Compile rules +#==================================================== +MKDIRS := $(TARGET_DIR) + +.PHONY : clean all +all: $(TARGET) + +$(TARGET): $(OBJS) $(CPP_OBJS) | $(MKDIRS) + @echo ... ld $@ + @echo ... $(TARGET) + @$(CC) $(CFLAGS) $(FLAG_LD) -o $(TARGET_DIR)/$@ $^ -Wl,--start-group $(MPI_LIBS) -Wl,--end-group + +$(CPP_OBJS) : $(OBJ_ROOT)/%.o : $(SRC_ROOT)/%.cpp + @echo @@@ c++ $^ + $(CXXCPP) $(FLAG_LD) $(CFLAGS) -c "$<" -o "$@" -w + +$(OBJS) : $(OBJ_ROOT)/%.o : $(SRC_ROOT)/%.c + @echo @@@ cc $^ + @$(CC) $(FLAG_LD) $(CFLAGS) -c "$<" -o "$@" -w + +$(MKDIRS): + mkdir -p $@ + +echo =========== $(TARGET) build success ================= + +clean: + @rm -rf $(TARGET_DIR) + @rm -rf $(OBJ_ROOT) + +cleanstream: + @rm -f *.h264 + @rm -f *.h265 + @rm -f *.jpg + @rm -f *.mjp + @rm -f *.mp4