#ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif /* End of #ifdef __cplusplus */ #include "rockiva/rockiva_ba_api.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rtsp_demo.h" #include "sample_comm.h" #include pthread_mutex_t g_rtsp_mutex = PTHREAD_MUTEX_INITIALIZER; static rtsp_demo_handle g_rtsplive = NULL; static rtsp_session_handle g_rtsp_session_0, g_rtsp_session_1, g_rtsp_session_2, g_rtsp_session_3; static int rociva_run_flag = 0; static RockIvaHandle rkba_handle; static RockIvaBaTaskParams initParams; static RockIvaInitParam globalParams; typedef struct _rkMpiCtx { SAMPLE_VI_CTX_S vi[4]; // camera 0: 0,1; camera 1: 2,3 SAMPLE_VENC_CTX_S venc[4]; } SAMPLE_MPI_CTX_S; static bool quit = false; static void sigterm_handler(int sig) { fprintf(stderr, "signal %d\n", sig); quit = true; } static int max_width = 1920; static int max_height = 1080; static RK_CHAR optstr[] = "?::r:f:W:H:w:h:s:n:b:S:x:y:"; static const struct option long_options[] = { {"hdr", required_argument, NULL, 'r'}, {"fps", required_argument, NULL, 'f'}, {"main_width", required_argument, NULL, 'W'}, {"main_height", required_argument, NULL, 'H'}, {"sub_width", required_argument, NULL, 'w'}, {"sub_height", required_argument, NULL, 'h'}, {"sensorid", required_argument, NULL, 's'}, {"enable_npu", required_argument, NULL, 'n'}, {"buf_share", required_argument, NULL, 'b'}, {"switch_res", required_argument, NULL, 'S'}, {"max_width", required_argument, NULL, 'x'}, {"max_height", required_argument, NULL, 'y'}, {"help", optional_argument, NULL, '?'}, {NULL, 0, NULL, 0}, }; static void *switch_resolution(void *arg) { RK_S32 s32Ret; RK_S32 width = max_width, height = max_height; RK_CODEC_ID_E enCodecType = RK_VIDEO_ID_HEVC; VENC_CHN_ATTR_S stAttr; VI_CHN_ATTR_S stChnAttr; MPP_CHN_S stSrcChn, stDestChn; VENC_RECV_PIC_PARAM_S stRecvParam; memset(&stRecvParam, 0, sizeof(VENC_RECV_PIC_PARAM_S)); stRecvParam.s32RecvPicNum = -1; while (!quit) { // switch every 10 seconds sleep(10); // stop venc s32Ret = RK_MPI_VENC_StopRecvFrame(0); if (s32Ret != RK_SUCCESS) { break; } s32Ret = RK_MPI_VENC_StopRecvFrame(2); if (s32Ret != RK_SUCCESS) { break; } // wait get stream usleep(1000); // change resolution printf("===change resolution===\n"); if (width == max_width) { width = 640; height = 360; } else { width = max_width; height = max_height; } stSrcChn.enModId = RK_ID_VI; stSrcChn.s32DevId = 0; stSrcChn.s32ChnId = 0; stDestChn.enModId = RK_ID_VENC; stDestChn.s32DevId = 0; stDestChn.s32ChnId = 0; // 1, unbind s32Ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_SYS_UnBind fail %x", s32Ret); } // 2, set venc RK_MPI_VENC_GetChnAttr(0, &stAttr); if (enCodecType == RK_VIDEO_ID_AVC) { stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; stAttr.stRcAttr.stH264Cbr.u32BitRate = 10 * 1024; stAttr.stRcAttr.stH264Cbr.u32Gop = 60; } else if (enCodecType == RK_VIDEO_ID_HEVC) { stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR; stAttr.stRcAttr.stH265Cbr.u32BitRate = 10 * 1024; stAttr.stRcAttr.stH265Cbr.u32Gop = 60; } else if (enCodecType == RK_VIDEO_ID_MJPEG) { stAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGCBR; stAttr.stRcAttr.stMjpegCbr.u32BitRate = 10 * 1024; } stAttr.stVencAttr.enType = enCodecType; stAttr.stVencAttr.u32PicWidth = width; stAttr.stVencAttr.u32PicHeight = height; stAttr.stVencAttr.u32VirWidth = width; stAttr.stVencAttr.u32VirHeight = height; stAttr.stVencAttr.u32MaxPicWidth = max_width; stAttr.stVencAttr.u32MaxPicHeight = max_height; RK_MPI_VENC_SetChnAttr(0, &stAttr); // 3, set vi s32Ret = RK_MPI_VI_GetChnAttr(0, 0, &stChnAttr); stChnAttr.stSize.u32Width = width; stChnAttr.stSize.u32Height = height; stChnAttr.stIspOpt.stMaxSize.u32Width = max_width; stChnAttr.stIspOpt.stMaxSize.u32Height = max_height; stChnAttr.stFrameRate.s32SrcFrameRate = -1; stChnAttr.stFrameRate.s32DstFrameRate = -1; s32Ret = RK_MPI_VI_SetChnAttr(0, 0, &stChnAttr); if (s32Ret != RK_SUCCESS) { RK_LOGD("RK_MPI_VI_SetChnAttr %d x %d fail, ret: %x", width, height, s32Ret); } else { RK_LOGD("====RK_MPI_VI_SetChnAttr %d x %d success====", width, height); } // 4, bind s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("bind %x ch venc failed", s32Ret); } stSrcChn.enModId = RK_ID_VI; stSrcChn.s32DevId = 1; stSrcChn.s32ChnId = 0; stDestChn.enModId = RK_ID_VENC; stDestChn.s32DevId = 0; stDestChn.s32ChnId = 2; // 1, unbind s32Ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_SYS_UnBind fail %x", s32Ret); } // 2, set venc RK_MPI_VENC_GetChnAttr(2, &stAttr); if (enCodecType == RK_VIDEO_ID_AVC) { stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; stAttr.stRcAttr.stH264Cbr.u32BitRate = 10 * 1024; stAttr.stRcAttr.stH264Cbr.u32Gop = 60; } else if (enCodecType == RK_VIDEO_ID_HEVC) { stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR; stAttr.stRcAttr.stH265Cbr.u32BitRate = 10 * 1024; stAttr.stRcAttr.stH265Cbr.u32Gop = 60; } else if (enCodecType == RK_VIDEO_ID_MJPEG) { stAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGCBR; stAttr.stRcAttr.stMjpegCbr.u32BitRate = 10 * 1024; } stAttr.stVencAttr.enType = enCodecType; stAttr.stVencAttr.u32PicWidth = width; stAttr.stVencAttr.u32PicHeight = height; stAttr.stVencAttr.u32VirWidth = width; stAttr.stVencAttr.u32VirHeight = height; stAttr.stVencAttr.u32MaxPicWidth = max_width; stAttr.stVencAttr.u32MaxPicHeight = max_height; RK_MPI_VENC_SetChnAttr(2, &stAttr); // 3, set vi s32Ret = RK_MPI_VI_GetChnAttr(1, 0, &stChnAttr); stChnAttr.stSize.u32Width = width; stChnAttr.stSize.u32Height = height; stChnAttr.stIspOpt.stMaxSize.u32Width = max_width; stChnAttr.stIspOpt.stMaxSize.u32Height = max_height; stChnAttr.stFrameRate.s32SrcFrameRate = -1; stChnAttr.stFrameRate.s32DstFrameRate = -1; s32Ret = RK_MPI_VI_SetChnAttr(1, 0, &stChnAttr); if (s32Ret != RK_SUCCESS) { RK_LOGD("RK_MPI_VI_SetChnAttr %d x %d fail, ret: %x", width, height, s32Ret); } else { RK_LOGD("====RK_MPI_VI_SetChnAttr %d x %d success====", width, height); } // 4, bind s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("bind %x ch venc failed", s32Ret); } // start venc RK_MPI_VENC_StartRecvFrame(0, &stRecvParam); RK_MPI_VENC_StartRecvFrame(2, &stRecvParam); } } /****************************************************************************** * function : venc thread ******************************************************************************/ static void *venc0_get_stream(void *pArgs) { printf("#Start %s , arg:%p\n", __func__, pArgs); SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; // char name[256] = {0}; // FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; while (!quit) { s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData); if (s32Ret == RK_SUCCESS) { RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount, ctx->stFrame.pstPack->u32Len); // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VENC_ReleaseStream(ctx); quit = true; break; } } PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len); pthread_mutex_lock(&g_rtsp_mutex); rtsp_tx_video(g_rtsp_session_0, pData, ctx->stFrame.pstPack->u32Len, ctx->stFrame.pstPack->u64PTS); rtsp_do_event(g_rtsplive); pthread_mutex_unlock(&g_rtsp_mutex); SAMPLE_COMM_VENC_ReleaseStream(ctx); loopCount++; } usleep(1000); } return RK_NULL; } static void *venc1_get_stream(void *pArgs) { printf("#Start %s , arg:%p\n", __func__, pArgs); SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; // char name[256] = {0}; // FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; while (!quit) { s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData); if (s32Ret == RK_SUCCESS) { RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount, ctx->stFrame.pstPack->u32Len); // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VENC_ReleaseStream(ctx); quit = true; break; } } PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len); pthread_mutex_lock(&g_rtsp_mutex); rtsp_tx_video(g_rtsp_session_1, pData, ctx->stFrame.pstPack->u32Len, ctx->stFrame.pstPack->u64PTS); rtsp_do_event(g_rtsplive); pthread_mutex_unlock(&g_rtsp_mutex); SAMPLE_COMM_VENC_ReleaseStream(ctx); loopCount++; } usleep(1000); } return RK_NULL; } static void *venc2_get_stream(void *pArgs) { printf("#Start %s , arg:%p\n", __func__, pArgs); SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; // char name[256] = {0}; // FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; while (!quit) { s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData); if (s32Ret == RK_SUCCESS) { RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount, ctx->stFrame.pstPack->u32Len); // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VENC_ReleaseStream(ctx); quit = true; break; } } PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len); pthread_mutex_lock(&g_rtsp_mutex); rtsp_tx_video(g_rtsp_session_2, pData, ctx->stFrame.pstPack->u32Len, ctx->stFrame.pstPack->u64PTS); rtsp_do_event(g_rtsplive); pthread_mutex_unlock(&g_rtsp_mutex); SAMPLE_COMM_VENC_ReleaseStream(ctx); loopCount++; } usleep(1000); } return RK_NULL; } static void *venc3_get_stream(void *pArgs) { printf("#Start %s , arg:%p\n", __func__, pArgs); SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; // char name[256] = {0}; // FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; while (!quit) { s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData); if (s32Ret == RK_SUCCESS) { RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount, ctx->stFrame.pstPack->u32Len); // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VENC_ReleaseStream(ctx); quit = true; break; } } PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len); pthread_mutex_lock(&g_rtsp_mutex); rtsp_tx_video(g_rtsp_session_3, pData, ctx->stFrame.pstPack->u32Len, ctx->stFrame.pstPack->u64PTS); rtsp_do_event(g_rtsplive); pthread_mutex_unlock(&g_rtsp_mutex); SAMPLE_COMM_VENC_ReleaseStream(ctx); loopCount++; } usleep(1000); } return RK_NULL; } void rkba_callback(const RockIvaBaResult *result, const RockIvaExecuteStatus status, void *userData) { if (result->objNum == 0) return; printf("status is %d, frame %d, result->objNum is %d\n", status, result->frameId, result->objNum); for (int i = 0; i < result->objNum; i++) { printf("topLeft:[%d,%d], bottomRight:[%d,%d]," "objId is %d, frameId is %d, score is %d, type is %d\n", result->triggerObjects[i].objInfo.rect.topLeft.x, result->triggerObjects[i].objInfo.rect.topLeft.y, result->triggerObjects[i].objInfo.rect.bottomRight.x, result->triggerObjects[i].objInfo.rect.bottomRight.y, result->triggerObjects[i].objInfo.objId, result->triggerObjects[i].objInfo.frameId, result->triggerObjects[i].objInfo.score, result->triggerObjects[i].objInfo.type); } } int rockiva_init() { RockIvaRetCode ret; // const char *model_type; memset(&initParams, 0, sizeof(initParams)); memset(&globalParams, 0, sizeof(globalParams)); snprintf(globalParams.modelPath, ROCKIVA_PATH_LENGTH, "/usr/lib/"); globalParams.coreMask = 0x04; globalParams.logLevel = ROCKIVA_LOG_ERROR; globalParams.detModel |= ROCKIVA_OBJECT_TYPE_FACE; globalParams.detModel |= ROCKIVA_OBJECT_TYPE_PERSON; globalParams.detModel |= ROCKIVA_OBJECT_TYPE_NON_VEHICLE; globalParams.detModel |= ROCKIVA_OBJECT_TYPE_VEHICLE; globalParams.imageInfo.width = 720; globalParams.imageInfo.height = 576; globalParams.imageInfo.format = ROCKIVA_IMAGE_FORMAT_YUV420SP_NV12; ROCKIVA_Init(&rkba_handle, ROCKIVA_MODE_VIDEO, &globalParams, NULL); printf("ROCKIVA_Init over\n"); // 构建一个区域入侵规则 int web_width = 704; int web_height = 480; int ri_x = 0; int ri_y = 0; int ri_w = 704; int ri_h = 480; initParams.baRules.areaInBreakRule[0].ruleEnable = 1; initParams.baRules.areaInBreakRule[0].sense = 50; initParams.baRules.areaInBreakRule[0].alertTime = 1000; // ms initParams.baRules.areaInBreakRule[0].minObjSize[2].height = 5; initParams.baRules.areaInBreakRule[0].minObjSize[2].width = 5; initParams.baRules.areaInBreakRule[0].event = ROCKIVA_BA_TRIP_EVENT_STAY; initParams.baRules.areaInBreakRule[0].ruleID = 0; initParams.baRules.areaInBreakRule[0].objType = ROCKIVA_OBJECT_TYPE_BITMASK(ROCKIVA_OBJECT_TYPE_PERSON); initParams.baRules.areaInBreakRule[0].area.pointNum = 4; initParams.baRules.areaInBreakRule[0].area.points[0].x = ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x); initParams.baRules.areaInBreakRule[0].area.points[0].y = ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y); initParams.baRules.areaInBreakRule[0].area.points[1].x = ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x + ri_w); initParams.baRules.areaInBreakRule[0].area.points[1].y = ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y); initParams.baRules.areaInBreakRule[0].area.points[2].x = ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x + ri_w); initParams.baRules.areaInBreakRule[0].area.points[2].y = ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y + ri_h); initParams.baRules.areaInBreakRule[0].area.points[3].x = ROCKIVA_PIXEL_RATION_CONVERT(web_width, ri_x); initParams.baRules.areaInBreakRule[0].area.points[3].y = ROCKIVA_PIXEL_RATION_CONVERT(web_height, ri_y + ri_h); printf("(%d,%d), (%d,%d), (%d,%d), (%d,%d)\n", initParams.baRules.areaInBreakRule[0].area.points[0].x, initParams.baRules.areaInBreakRule[0].area.points[0].y, initParams.baRules.areaInBreakRule[0].area.points[1].x, initParams.baRules.areaInBreakRule[0].area.points[1].y, initParams.baRules.areaInBreakRule[0].area.points[2].x, initParams.baRules.areaInBreakRule[0].area.points[2].y, initParams.baRules.areaInBreakRule[0].area.points[3].x, initParams.baRules.areaInBreakRule[0].area.points[3].y); initParams.aiConfig.detectResultMode = 0; ret = ROCKIVA_BA_Init(rkba_handle, &initParams, rkba_callback); if (ret != ROCKIVA_RET_SUCCESS) { printf("ROCKIVA_BA_Init error %d\n", ret); return -1; } printf("ROCKIVA_BA_Init success\n"); rociva_run_flag = 1; return ret; } int rockiva_deinit() { rociva_run_flag = 0; ROCKIVA_BA_Release(rkba_handle); ROCKIVA_Release(rkba_handle); return 0; } int rkipc_rockiva_write_nv12_frame_by_fd(uint16_t width, uint16_t height, uint32_t frame_id, int32_t fd) { int ret; if (!rociva_run_flag) return 0; RockIvaImage *image = (RockIvaImage *)malloc(sizeof(RockIvaImage)); memset(image, 0, sizeof(RockIvaImage)); image->info.transformMode = ROCKIVA_IMAGE_TRANSFORM_NONE; image->info.width = width; image->info.height = height; image->info.format = ROCKIVA_IMAGE_FORMAT_YUV420SP_NV12; image->frameId = frame_id; image->dataAddr = NULL; image->dataPhyAddr = NULL; image->dataFd = fd; ret = ROCKIVA_PushFrame(rkba_handle, image, NULL); free(image); return ret; } pthread_t get_vi_to_npu_thread; static void *rkipc_get_vi_to_npu(void *arg) { printf("#Start %s thread, arg:%p\n", __func__, arg); int s32Ret; int32_t loopCount = 0; VIDEO_FRAME_INFO_S stViFrame; while (!quit) { s32Ret = RK_MPI_VI_GetChnFrame(0, 1, &stViFrame, 1000); if (s32Ret == RK_SUCCESS) { RK_LOGD("loopCount is %d, w is %d, h is %d, seq is %d, pts is %lld\n", loopCount, stViFrame.stVFrame.u32Width, stViFrame.stVFrame.u32Height, stViFrame.stVFrame.u32TimeRef, stViFrame.stVFrame.u64PTS / 1000); // void *data = RK_MPI_MB_Handle2VirAddr(stViFrame.stVFrame.pMbBlk); int32_t fd = RK_MPI_MB_Handle2Fd(stViFrame.stVFrame.pMbBlk); rkipc_rockiva_write_nv12_frame_by_fd( stViFrame.stVFrame.u32Width, stViFrame.stVFrame.u32Height, loopCount, fd); s32Ret = RK_MPI_VI_ReleaseChnFrame(0, 1, &stViFrame); if (s32Ret != RK_SUCCESS) printf("RK_MPI_VI_ReleaseChnFrame fail %x\n", s32Ret); loopCount++; } else { printf("RK_MPI_VI_GetChnFrame timeout %x\n", s32Ret); } } return NULL; } static void print_usage(const RK_CHAR *name) { printf("usage example:\n"); printf("\t%s -s 0 -W init_width -H init_height -w 720 -h 576 -f 30 -r 0 -s 1 -W init_width -H init_height -w " "720 -h 576 -f 30 -r 0 -n 1 -S 0 -x max_width -y max_height\n", name); printf("\trtsp://xx.xx.xx.xx/live/0, sensor 0 main-stream, Default OPEN\n"); printf("\trtsp://xx.xx.xx.xx/live/1, sensor 0 sub-stream, Default OPEN\n"); printf("\trtsp://xx.xx.xx.xx/live/2, sensor 1 main-stream, Default OPEN\n"); printf("\trtsp://xx.xx.xx.xx/live/3, sensor 1 sub-stream, Default OPEN\n"); printf("\t-s | --sensor id\n"); printf("\t-f | --fps: frame per second, Default 15\n"); printf("\t-r | --hdr: high dynamic range, Default 0\n"); printf("\t-W | --main_width: main-stream with, Default max_width\n"); printf("\t-H | --main_height: main-stream height, Default max_height\n"); printf("\t-w | --sub_width: sub-stream with, Default 704\n"); printf("\t-h | --sub_height: sub-stream height, Default 576\n"); printf("\t-n | --enable_npu: enable npu, Default 1\n"); printf("\t-b | --buf_share: enable buf share, Default 1\n"); printf("\t-S | --switch_res: switch resolution, Default 0\n"); printf("\t-x | --max_width: max width, Default 1920\n"); printf("\t-y | --max_height: max height, Default 1080\n"); } /****************************************************************************** * function : main() * Description : main ******************************************************************************/ void handle_pipe(int sig) { printf("%s sig = %d\n", __func__, sig); } int main(int argc, char *argv[]) { // RK_S32 s32Ret = RK_FAILURE; SAMPLE_MPI_CTX_S *ctx; int cam_0_fps = 15; int cam_0_enable_hdr = 0; int cam_0_video_0_width = max_width; int cam_0_video_0_height = max_height; int cam_0_video_1_width = 704; int cam_0_video_1_height = 576; // int cam_0_video_2_width = 896; // int cam_0_video_2_height = 512; int cam_1_fps = 15; int cam_1_enable_hdr = 0; int cam_1_video_0_width = max_width; int cam_1_video_0_height = max_height; int cam_1_video_1_width = 704; int cam_1_video_1_height = 576; int enable_npu = 1; int enable_buf_share = 1; CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H265; VENC_RC_MODE_E enRcMode = VENC_RC_MODE_H265CBR; RK_CHAR *pCodecName = "H265"; RK_S32 s32CamId = -1; MPP_CHN_S vi_chn[6], venc_chn[4]; RK_CHAR *pOutPathVenc = "/userdata"; RK_S32 s32CamNum = 4; RK_S32 s32loopCnt = -1; RK_S32 s32BitRate = 2 * 1024; RK_S32 s32SubBitRate = 512; RK_S32 switch_res = 0; RK_S32 i; char *iq_file_dir = "/oem/usr/share/iqfiles"; if (argc < 2) { print_usage(argv[0]); return 0; } struct sigaction action; action.sa_handler = handle_pipe; sigemptyset(&action.sa_mask); action.sa_flags = 0; sigaction(SIGPIPE, &action, NULL); ctx = (SAMPLE_MPI_CTX_S *)(malloc(sizeof(SAMPLE_MPI_CTX_S))); memset(ctx, 0, sizeof(SAMPLE_MPI_CTX_S)); signal(SIGINT, sigterm_handler); #ifdef RKAIQ RK_BOOL bMultictx = RK_TRUE; #endif int c; while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) { switch (c) { case 's': s32CamId = atoi(optarg); break; case 'f': if (s32CamId == 0) cam_0_fps = atoi(optarg); if (s32CamId == 1) cam_1_fps = atoi(optarg); break; case 'r': if (s32CamId == 0) cam_0_enable_hdr = atoi(optarg); if (s32CamId == 1) cam_1_enable_hdr = atoi(optarg); break; case 'W': if (s32CamId == 0) cam_0_video_0_width = atoi(optarg); if (s32CamId == 1) cam_1_video_0_width = atoi(optarg); break; case 'H': if (s32CamId == 0) cam_0_video_0_height = atoi(optarg); if (s32CamId == 1) cam_1_video_0_height = atoi(optarg); break; case 'w': if (s32CamId == 0) cam_0_video_1_width = atoi(optarg); if (s32CamId == 1) cam_1_video_1_width = atoi(optarg); break; case 'h': if (s32CamId == 0) cam_0_video_1_height = atoi(optarg); if (s32CamId == 1) cam_1_video_1_height = atoi(optarg); break; case 'n': enable_npu = atoi(optarg); break; case 'b': enable_buf_share = atoi(optarg); break; case 'S': switch_res = atoi(optarg); break; case 'x': max_width = atoi(optarg); break; case 'y': max_height = atoi(optarg); break; case '?': default: print_usage(argv[0]); return 0; } } printf("sensor 0: main:%d*%d, sub:%d*%d\n", cam_0_video_0_width, cam_0_video_0_height, cam_0_video_1_width, cam_0_video_1_height); printf("sensor 1: main:%d*%d, sub:%d*%d\n", cam_1_video_0_width, cam_1_video_0_height, cam_1_video_1_width, cam_1_video_1_height); if (cam_0_video_0_width <= 0 || cam_1_video_0_width <= 0 || cam_0_video_0_height <= 0 || cam_1_video_0_height <= 0) { printf("invalid main stream width/height,please check!\n"); return -1; } printf("#CodecName:%s\n", pCodecName); printf("#IQ Path: %s\n", iq_file_dir); if (iq_file_dir) { #ifdef RKAIQ printf("#Rkaiq XML DirPath: %s\n", iq_file_dir); printf("#bMultictx: %d\n\n", bMultictx); rk_aiq_working_mode_t hdr_mode_0 = RK_AIQ_WORKING_MODE_NORMAL; rk_aiq_working_mode_t hdr_mode_1 = RK_AIQ_WORKING_MODE_NORMAL; if (cam_0_enable_hdr) hdr_mode_0 = RK_AIQ_WORKING_MODE_ISP_HDR2; if (cam_1_enable_hdr) hdr_mode_1 = RK_AIQ_WORKING_MODE_ISP_HDR2; SAMPLE_COMM_ISP_Init(0, hdr_mode_0, bMultictx, iq_file_dir); SAMPLE_COMM_ISP_Run(0); SAMPLE_COMM_ISP_SetFrameRate(0, cam_0_fps); SAMPLE_COMM_ISP_Init(1, hdr_mode_1, bMultictx, iq_file_dir); SAMPLE_COMM_ISP_Run(1); SAMPLE_COMM_ISP_SetFrameRate(1, cam_1_fps); #endif } // init rtsp g_rtsplive = create_rtsp_demo(554); g_rtsp_session_0 = rtsp_new_session(g_rtsplive, "/live/0"); g_rtsp_session_1 = rtsp_new_session(g_rtsplive, "/live/1"); g_rtsp_session_2 = rtsp_new_session(g_rtsplive, "/live/2"); g_rtsp_session_3 = rtsp_new_session(g_rtsplive, "/live/3"); rtsp_set_video(g_rtsp_session_0, RTSP_CODEC_ID_VIDEO_H265, NULL, 0); rtsp_set_video(g_rtsp_session_1, RTSP_CODEC_ID_VIDEO_H265, NULL, 0); rtsp_set_video(g_rtsp_session_2, RTSP_CODEC_ID_VIDEO_H265, NULL, 0); rtsp_set_video(g_rtsp_session_3, RTSP_CODEC_ID_VIDEO_H265, NULL, 0); rtsp_sync_video_ts(g_rtsp_session_0, rtsp_get_reltime(), rtsp_get_ntptime()); rtsp_sync_video_ts(g_rtsp_session_1, rtsp_get_reltime(), rtsp_get_ntptime()); rtsp_sync_video_ts(g_rtsp_session_2, rtsp_get_reltime(), rtsp_get_ntptime()); rtsp_sync_video_ts(g_rtsp_session_3, rtsp_get_reltime(), rtsp_get_ntptime()); if (enable_npu) rockiva_init(); if (RK_MPI_SYS_Init() != RK_SUCCESS) { goto __FAILED; } // Init VI and VENC 0~4 for (i = 0; i < s32CamNum; i++) { if (i == 0) { ctx->vi[i].u32Width = cam_0_video_0_width; ctx->vi[i].u32Height = cam_0_video_0_height; ctx->vi[i].bWrapIfEnable = RK_TRUE; ctx->vi[i].u32BufferLine = ctx->vi[i].u32Height; } if (i == 1) { ctx->vi[i].u32Width = cam_0_video_1_width; ctx->vi[i].u32Height = cam_0_video_1_height; } if (i == 2) { ctx->vi[i].u32Width = cam_1_video_0_width; ctx->vi[i].u32Height = cam_1_video_0_height; ctx->vi[i].bWrapIfEnable = RK_TRUE; ctx->vi[i].u32BufferLine = ctx->vi[i].u32Height; } if (i == 3) { ctx->vi[i].u32Width = cam_1_video_1_width; ctx->vi[i].u32Height = cam_1_video_1_height; } if (i < 2) { ctx->vi[i].s32DevId = 0; ctx->vi[i].u32PipeId = 0; ctx->vi[i].s32ChnId = i; } else { ctx->vi[i].s32DevId = 1; ctx->vi[i].u32PipeId = 1; ctx->vi[i].s32ChnId = i - 2; } ctx->vi[i].stChnAttr.stIspOpt.stMaxSize.u32Width = max_width;//ctx->vi[i].u32Width;//初始化分辨率,按照最大 ctx->vi[i].stChnAttr.stIspOpt.stMaxSize.u32Height = max_height;//ctx->vi[i].u32Height;//初始化分辨率,按照最大 ctx->vi[i].stChnAttr.stIspOpt.u32BufCount = 1; ctx->vi[i].stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF; ctx->vi[i].stChnAttr.u32Depth = 0; ctx->vi[i].stChnAttr.enPixelFormat = RK_FMT_YUV420SP; ctx->vi[i].stChnAttr.enCompressMode = COMPRESS_MODE_NONE; ctx->vi[i].stChnAttr.stFrameRate.s32SrcFrameRate = -1; ctx->vi[i].stChnAttr.stFrameRate.s32DstFrameRate = -1; if ((i == 1) && enable_npu) { // NPU only 10 fps, need anothor buffer ctx->vi[i].stChnAttr.stIspOpt.u32BufCount = 3; ctx->vi[i].stChnAttr.u32Depth = 1; pthread_create(&get_vi_to_npu_thread, NULL, rkipc_get_vi_to_npu, NULL); } SAMPLE_COMM_VI_CreateChn(&ctx->vi[i]); vi_chn[i].enModId = RK_ID_VI; vi_chn[i].s32DevId = ctx->vi[i].s32DevId; vi_chn[i].s32ChnId = ctx->vi[i].s32ChnId; ctx->venc[i].s32ChnId = i; if (i == 0) { ctx->venc[i].u32Width = cam_0_video_0_width; ctx->venc[i].u32Height = cam_0_video_0_height; ctx->venc[i].u32BuffSize = max_width * max_height / 4; ctx->venc[i].u32Fps = cam_0_fps; ctx->venc[i].bWrapIfEnable = RK_TRUE; ctx->venc[i].u32BufferLine = ctx->venc[i].u32Height; ctx->venc[i].u32BitRate = s32BitRate; } if (i == 1) { ctx->venc[i].u32Width = cam_0_video_1_width; ctx->venc[i].u32Height = cam_0_video_1_height; ctx->venc[i].u32BuffSize = ctx->venc[i].u32Width * ctx->venc[i].u32Height / 4; ctx->venc[i].u32Fps = cam_0_fps; ctx->venc[i].u32BitRate = s32SubBitRate; } if (i == 2) { ctx->venc[i].u32Width = cam_1_video_0_width; ctx->venc[i].u32Height = cam_1_video_0_height; ctx->venc[i].u32BuffSize = max_width * max_height / 4; ctx->venc[i].u32Fps = cam_1_fps; ctx->venc[i].bWrapIfEnable = RK_TRUE; ctx->venc[i].u32BufferLine = ctx->venc[i].u32Height; ctx->venc[i].u32BitRate = s32BitRate; } if (i == 3) { ctx->venc[i].u32Width = cam_1_video_1_width; ctx->venc[i].u32Height = cam_1_video_1_height; ctx->venc[i].u32BuffSize = ctx->venc[i].u32Width * ctx->venc[i].u32Height / 4; ctx->venc[i].u32Fps = cam_1_fps; ctx->venc[i].u32BitRate = s32SubBitRate; } ctx->venc[i].u32Gop = cam_0_fps * 3; ctx->venc[i].enCodecType = enCodecType; ctx->venc[i].enRcMode = enRcMode; if (i == 0) ctx->venc[i].getStreamCbFunc = venc0_get_stream; if (i == 1) ctx->venc[i].getStreamCbFunc = venc1_get_stream; if (i == 2) ctx->venc[i].getStreamCbFunc = venc2_get_stream; if (i == 3) ctx->venc[i].getStreamCbFunc = venc3_get_stream; ctx->venc[i].s32loopCount = s32loopCnt; ctx->venc[i].dstFilePath = pOutPathVenc; // H264 66:Baseline 77:Main Profile 100:High Profile // H265 0:Main Profile 1:Main 10 Profile // MJPEG 0:Baseline ctx->venc[i].stChnAttr.stVencAttr.u32Profile = 0; ctx->venc[i].stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP; ctx->venc[i].enable_buf_share = enable_buf_share; SAMPLE_COMM_VENC_CreateChn(&ctx->venc[i]); printf("venc[%d]:u32BufSize:%d\n", i, ctx->venc[i].stChnAttr.stVencAttr.u32BufSize); venc_chn[i].enModId = RK_ID_VENC; venc_chn[i].s32DevId = 0; venc_chn[i].s32ChnId = ctx->venc[i].s32ChnId; } SAMPLE_COMM_Bind(&vi_chn[0], &venc_chn[0]); SAMPLE_COMM_Bind(&vi_chn[1], &venc_chn[1]); SAMPLE_COMM_Bind(&vi_chn[2], &venc_chn[2]); SAMPLE_COMM_Bind(&vi_chn[3], &venc_chn[3]); pthread_t tsw; if (switch_res) pthread_create(&tsw, NULL, switch_resolution, NULL); printf("%s initial finish\n", __func__); while (!quit) { sleep(1); } if (switch_res) pthread_join(tsw, NULL); printf("%s exit!\n", __func__); for (i = 0; i < s32CamNum; i++) { if (ctx->venc[i].getStreamCbFunc) { pthread_join(ctx->venc[i].getStreamThread, NULL); } } if (enable_npu) rockiva_deinit(); pthread_join(get_vi_to_npu_thread, NULL); if (g_rtsplive) rtsp_del_demo(g_rtsplive); SAMPLE_COMM_UnBind(&vi_chn[0], &venc_chn[0]); SAMPLE_COMM_UnBind(&vi_chn[1], &venc_chn[1]); SAMPLE_COMM_UnBind(&vi_chn[2], &venc_chn[2]); SAMPLE_COMM_UnBind(&vi_chn[3], &venc_chn[3]); // Destroy VI[0] for (i = 0; i < s32CamNum; i++) { SAMPLE_COMM_VENC_DestroyChn(&ctx->venc[i]); SAMPLE_COMM_VI_DestroyChn(&ctx->vi[i]); } __FAILED: RK_MPI_SYS_Exit(); if (iq_file_dir) { #ifdef RKAIQ for (int i = 0; i < s32CamNum; i++) { SAMPLE_COMM_ISP_Stop(i); } #endif } if (ctx) { free(ctx); ctx = RK_NULL; } return 0; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* End of #ifdef __cplusplus */