/* * Copyright 2021 Rockchip Electronics 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. * */ #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif /* End of #ifdef __cplusplus */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rtsp_demo.h" #include "sample_comm.h" #include "sample_comm_aov.h" static sem_t g_iva_semaphore; static SAMPLE_IVA_CTX_S iva_ctx; static char *path = NULL; static RK_S32 loop_count = 0; static bool quit = false; static int quit_result = RK_SUCCESS; static void sigterm_handler(int sig) { fprintf(stderr, "signal %d\n", sig); quit = true; quit_result = RK_SUCCESS; } static void program_handle_error(const char *func, RK_U32 line) { printf("func: <%s> line: <%d> error exit!", func, line); quit = true; quit_result = RK_FAILURE; } static void program_normal_exit(const char *func, RK_U32 line) { printf("func: <%s> line: <%d> normal exit!", func, line); quit = true; quit_result = RK_SUCCESS; } static RK_CHAR optstr[] = "?:w:h:l:p:"; static const struct option long_options[] = { {"loop_count", required_argument, NULL, 'l'}, {"path", required_argument, NULL, 'p'}, {"width", required_argument, NULL, 'w'}, {"height", required_argument, NULL, 'h'}, {"suspend_time", required_argument, NULL, 's' + 't'}, {"help", optional_argument, NULL, '?'}, {NULL, 0, NULL, 0}, }; /****************************************************************************** * function : show usage ******************************************************************************/ static void print_usage(const RK_CHAR *name) { printf("usage example:\n"); printf("\t%s -w 720 -h 480 -l 1 -p /mnt/sdcard/test_image.yuv\n", name); printf("\t-w | --width: input image with, Default 720\n"); printf("\t-h | --height: input image height, Default 480\n"); printf("\t-l | --loop_count: test loop count, 1\n"); printf("\t-p | --path: input image path, Default NULL\n"); printf("\t--suspend_time: set aov suspend time, Default: 1000ms\n"); } static void rkIvaEvent_callback(const RockIvaDetectResult *result, const RockIvaExecuteStatus status, void *userData) { RK_LOGI("objnum %d, status %d", result->objNum, status); for (int i = 0; i < result->objNum; i++) { RK_LOGI("topLeft:[%d,%d], bottomRight:[%d,%d]," "objId is %d, frameId is %d, score is %d, type is %d\n", result->objInfo[i].rect.topLeft.x, result->objInfo[i].rect.topLeft.y, result->objInfo[i].rect.bottomRight.x, result->objInfo[i].rect.bottomRight.y, result->objInfo[i].objId, result->objInfo[i].frameId, result->objInfo[i].score, result->objInfo[i].type); } } static void rkIvaFrame_releaseCallBack(const RockIvaReleaseFrames *releaseFrames, void *userdata) { /* when iva handle out of the video frame,this func will be called*/ RK_LOGD("release iva frame success!"); sem_post(&g_iva_semaphore); } static void *send_frame_to_iva_thread(void *pArgs) { prctl(PR_SET_NAME, "send_frame_to_iva_thread"); RK_S32 s32Ret = RK_FAILURE; RK_S32 input_file_fd = path ? open(path, O_RDONLY) : -1; RockIvaImage input_image; RK_U32 size = iva_ctx.u32ImageWidth * iva_ctx.u32ImageHeight * 3 / 2; RK_S32 i = 0; RK_S32 pool_id; MB_POOL_CONFIG_S pool_cfg; MB_BLK blk; void *input_image_vaddr; RK_S32 input_image_fd; memset(&pool_cfg, 0, sizeof(MB_POOL_CONFIG_S)); pool_cfg.u64MBSize = size; pool_cfg.u32MBCnt = 1; pool_cfg.enAllocType = MB_ALLOC_TYPE_DMA; pool_cfg.bPreAlloc = RK_FALSE; pool_id = RK_MPI_MB_CreatePool(&pool_cfg); if (pool_id == MB_INVALID_POOLID) { RK_LOGE("create mb pool failed"); program_handle_error(__func__, __LINE__); return NULL; } // read test image blk = RK_MPI_MB_GetMB(pool_id, size, RK_TRUE); if (blk == MB_INVALID_HANDLE) { RK_LOGE("get mb block failed"); program_handle_error(__func__, __LINE__); return NULL; } input_image_vaddr = RK_MPI_MB_Handle2VirAddr(blk); input_image_fd = RK_MPI_MB_Handle2Fd(blk); if (input_file_fd < 0) { RK_LOGE("open %s failed because %s, use empty image as input", path, strerror(errno)); memset(input_image_vaddr, 0, size); RK_MPI_SYS_MmzFlushCache(blk, RK_FALSE); } else { s32Ret = read(input_file_fd, input_image_vaddr, size); RK_LOGI("input image size %d", s32Ret); RK_MPI_SYS_MmzFlushCache(blk, RK_FALSE); } sem_init(&g_iva_semaphore, 0, 0); while (!quit && i < loop_count) { RK_LOGI("loop count %d", i++); // send test image to iva input_image.info.transformMode = iva_ctx.eImageTransform; input_image.info.width = iva_ctx.u32ImageWidth; input_image.info.height = iva_ctx.u32ImageHeight; input_image.info.format = iva_ctx.eImageFormat; input_image.frameId = i; input_image.dataAddr = NULL; input_image.dataPhyAddr = NULL; input_image.dataFd = input_image_fd; s32Ret = ROCKIVA_PushFrame(iva_ctx.ivahandle, &input_image, NULL); if (s32Ret < 0) { RK_LOGE("ROCKIVA_PushFrame failed %#X", s32Ret); program_handle_error(__func__, __LINE__); break; } // wait for iva resule sem_wait(&g_iva_semaphore); // suspend and resume SAMPLE_COMM_AOV_EnterSleep(); } sem_destroy(&g_iva_semaphore); if (input_file_fd) close(input_file_fd); RK_MPI_MB_ReleaseMB(blk); RK_MPI_MB_DestroyPool(pool_id); program_normal_exit(__func__, __LINE__); RK_LOGE("send_frame_to_iva_thread exit !!!"); return RK_NULL; } /****************************************************************************** * function : main() * Description : main ******************************************************************************/ int main(int argc, char *argv[]) { RK_U32 u32IvaWidth = 720; RK_U32 u32IvaHeight = 480; RK_U32 u32IvaDetectFrameRate = 10; RK_CHAR *pIvaModelPath = "/oem/usr/lib/"; RK_S32 s32Ret; RK_S32 s32SuspendTime = 1000; pthread_t iva_thread_id; if (argc < 2) { print_usage(argv[0]); return 0; } signal(SIGINT, sigterm_handler); int c; while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) { const char *tmp_optarg = optarg; switch (c) { case 'w': u32IvaWidth = atoi(optarg); break; case 'h': u32IvaHeight = atoi(optarg); break; case 'l': loop_count = atoi(optarg); break; case 's' + 't': s32SuspendTime = atoi(optarg); break; case 'p': path = optarg; break; case '?': default: print_usage(argv[0]); return 0; } } RK_MPI_SYS_Init(); SAMPLE_COMM_AOV_SetSuspendTime(s32SuspendTime); /* Init iva */ iva_ctx.pModelDataPath = pIvaModelPath; iva_ctx.u32ImageWidth = u32IvaWidth; iva_ctx.u32ImageHeight = u32IvaHeight; iva_ctx.u32DetectStartX = 0; iva_ctx.u32DetectStartY = 0; iva_ctx.u32DetectWidth = u32IvaWidth; iva_ctx.u32DetectHight = u32IvaHeight; iva_ctx.eImageTransform = ROCKIVA_IMAGE_TRANSFORM_NONE; iva_ctx.eImageFormat = ROCKIVA_IMAGE_FORMAT_YUV420SP_NV12; iva_ctx.eModeType = ROCKIVA_DET_MODEL_PFP; iva_ctx.u32IvaDetectFrameRate = u32IvaDetectFrameRate; iva_ctx.detectResultCallback = rkIvaEvent_callback; iva_ctx.releaseCallback = rkIvaFrame_releaseCallBack; iva_ctx.eIvaMode = ROCKIVA_MODE_DETECT; s32Ret = SAMPLE_COMM_IVA_Create(&iva_ctx); if (s32Ret != RK_SUCCESS) { RK_LOGE("SAMPLE_COMM_IVA_Create failure:%#X", s32Ret); return RK_FAILURE; } // /* VI[1] IVA thread launch */ pthread_create(&iva_thread_id, 0, send_frame_to_iva_thread, NULL); printf("%s initial finish\n", __func__); while (!quit) { sleep(1); } printf("%s exit!\n", __func__); /* Destroy IVA */ pthread_join(iva_thread_id, RK_NULL); SAMPLE_COMM_IVA_Destroy(&iva_ctx); RK_MPI_SYS_Exit(); return quit_result; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* End of #ifdef __cplusplus */