/* * 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 "sample_comm.h" typedef struct _rkMpiCtx { SAMPLE_VI_CTX_S vi[6]; } SAMPLE_MPI_CTX_S; static bool quit = false; static void sigterm_handler(int sig) { fprintf(stderr, "signal %d\n", sig); quit = true; } static RK_CHAR optstr[] = "?::a::f:w:h:c:o:n:l:m:"; static const struct option long_options[] = { {"aiq", optional_argument, NULL, 'a'}, {"pixel_format", optional_argument, NULL, 'f'}, {"width", required_argument, NULL, 'w'}, {"height", required_argument, NULL, 'h'}, {"chn_id", required_argument, NULL, 'c'}, {"output_path", required_argument, NULL, 'o'}, {"camera_num", required_argument, NULL, 'n'}, {"loop_count", required_argument, NULL, 'l'}, {"hdr_mode", required_argument, NULL, 'h' + 'm'}, {"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 1920 -h 1080 -a /etc/iqfiles/ -n 2 -l 10 -o /data/\n", name); #if (defined RKAIQ) && (defined UAPI2) printf("\t-a | --aiq: enable aiq with dirpath provided, eg:-a /etc/iqfiles/, " "set dirpath empty to using path by default, without this option aiq " "should run in other application\n"); #endif printf("\t-f | --pixel_format: camera Format, Default nv12, " "Value:nv12,nv16,uyvy,rgb565,xbgr8888.\n"); printf("\t-w | --width: camera width, Default 1920\n"); printf("\t-h | --height: camera height, Default 1080\n"); printf("\t-c | --chn_id: channel id, default: 0\n"); printf("\t-o | --output_path: vi output file path, Default NULL\n"); printf("\t-n | --camera_num: camera number, Default 2\n"); printf("\t-l | --loop_count: loop count, Default -1\n"); printf("\t--hdr_mode: set hdr mode, 0: normal 1: HDR2, 2: HDR3, Default: 0\n"); } /****************************************************************************** * function : vi thread ******************************************************************************/ static void *vi_get_stream(void *pArgs) { SAMPLE_VI_CTX_S *ctx = (SAMPLE_VI_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; char name[256] = {0}; FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; if (ctx->dstFilePath) { snprintf(name, sizeof(name), "/%s/vi_%d.bin", ctx->dstFilePath, ctx->s32DevId); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32DevId, ctx->dstFilePath); quit = true; return RK_NULL; } } while (!quit) { s32Ret = SAMPLE_COMM_VI_GetChnFrame(ctx, &pData); if (s32Ret == RK_SUCCESS) { if (ctx->stViFrame.stVFrame.u64PrivateData <= 0) { // SAMPLE_COMM_VI_ReleaseChnFrame(ctx); // continue; } // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VI_ReleaseChnFrame(ctx); quit = true; break; } } if (fp) { fwrite(pData, 1, ctx->stViFrame.stVFrame.u64PrivateData, fp); fflush(fp); } printf( "SAMPLE_COMM_VI_GetChnFrame DevId %d ok:data %p size:%llu loop:%d seq:%d " "pts:%lld ms\n", ctx->s32DevId, pData, ctx->stViFrame.stVFrame.u64PrivateData, loopCount, ctx->stViFrame.stVFrame.u32TimeRef, ctx->stViFrame.stVFrame.u64PTS / 1000); SAMPLE_COMM_VI_ReleaseChnFrame(ctx); loopCount++; } usleep(1000); } if (fp) fclose(fp); return RK_NULL; } /****************************************************************************** * function : main() * Description : main ******************************************************************************/ int main(int argc, char *argv[]) { RK_S32 s32Ret = RK_FAILURE; SAMPLE_MPI_CTX_S *ctx; int video_width = 1920; int video_height = 1080; RK_CHAR *pOutPath = NULL; RK_S32 i; RK_S32 s32CamNum = 2; RK_S32 s32ChnId = 0; RK_S32 s32loopCnt = -1; PIXEL_FORMAT_E PixelFormat = RK_FMT_YUV420SP; COMPRESS_MODE_E CompressMode = COMPRESS_MODE_NONE; rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL; MPP_CHN_S stSrcChn, stDestChn; pthread_t vi_thread_id[6]; if (argc < 2) { print_usage(argv[0]); return 0; } ctx = (SAMPLE_MPI_CTX_S *)(malloc(sizeof(SAMPLE_MPI_CTX_S))); memset(ctx, 0, sizeof(SAMPLE_MPI_CTX_S)); signal(SIGINT, sigterm_handler); #if (defined RKAIQ) && (defined UAPI2) RK_BOOL bMultictx = RK_FALSE; #endif int c; char *iq_file_dir = NULL; while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) { const char *tmp_optarg = optarg; switch (c) { case 'a': if (!optarg && NULL != argv[optind] && '-' != argv[optind][0]) { tmp_optarg = argv[optind++]; } if (tmp_optarg) { iq_file_dir = (char *)tmp_optarg; } else { iq_file_dir = NULL; } break; case 'f': if (!strcmp(optarg, "nv12")) { PixelFormat = RK_FMT_YUV420SP; } else if (!strcmp(optarg, "nv16")) { PixelFormat = RK_FMT_YUV422SP; } else if (!strcmp(optarg, "uyvy")) { PixelFormat = RK_FMT_YUV422_UYVY; } else if (!strcmp(optarg, "rgb565")) { PixelFormat = RK_FMT_RGB565; s32ChnId = 1; } else if (!strcmp(optarg, "xbgr8888")) { PixelFormat = RK_FMT_XBGR8888; s32ChnId = 1; } else { RK_LOGE("this pixel_format is not supported in the sample"); print_usage(argv[0]); goto __FAILED2; } break; case 'w': video_width = atoi(optarg); break; case 'h': video_height = atoi(optarg); break; case 'c': s32ChnId = atoi(optarg); break; case 'o': pOutPath = optarg; break; case 'n': s32CamNum = atoi(optarg); break; case 'l': s32loopCnt = atoi(optarg); break; case 'h' + 'm': if (atoi(optarg) == 0) { hdr_mode = RK_AIQ_WORKING_MODE_NORMAL; } else if (atoi(optarg) == 1) { hdr_mode = RK_AIQ_WORKING_MODE_ISP_HDR2; } else if (atoi(optarg) == 2) { hdr_mode = RK_AIQ_WORKING_MODE_ISP_HDR3; } else { RK_LOGE("input hdr_mode is not support(error)"); print_usage(argv[0]); goto __FAILED2; } break; case '?': default: print_usage(argv[0]); return 0; } } printf("#CameraNum: %d\n", s32CamNum); printf("#Output Path: %s\n", pOutPath); printf("#IQ Path: %s\n", iq_file_dir); if (iq_file_dir) { #if (defined RKAIQ) && (defined UAPI2) printf("#Rkaiq XML DirPath: %s\n", iq_file_dir); printf("#bMultictx: %d\n\n", bMultictx); rk_aiq_camgroup_instance_cfg_t camgroup_cfg; memset(&camgroup_cfg, 0, sizeof(camgroup_cfg)); camgroup_cfg.sns_num = s32CamNum; camgroup_cfg.config_file_dir = iq_file_dir; SAMPLE_COMM_ISP_CamGroup_Init(0, hdr_mode, bMultictx, &camgroup_cfg); #endif } if (RK_MPI_SYS_Init() != RK_SUCCESS) { goto __FAILED; } // Init VI for (i = 0; i < s32CamNum; i++) { ctx->vi[i].u32Width = video_width; ctx->vi[i].u32Height = video_height; ctx->vi[i].s32DevId = i; ctx->vi[i].u32PipeId = ctx->vi[i].s32DevId; ctx->vi[i].s32ChnId = s32ChnId; ctx->vi[i].stChnAttr.stIspOpt.u32BufCount = 2; ctx->vi[i].stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF; ctx->vi[i].stChnAttr.u32Depth = 1; ctx->vi[i].stChnAttr.enPixelFormat = PixelFormat; ctx->vi[i].stChnAttr.enCompressMode = CompressMode; ctx->vi[i].stChnAttr.stFrameRate.s32SrcFrameRate = -1; ctx->vi[i].stChnAttr.stFrameRate.s32DstFrameRate = -1; ctx->vi[i].dstFilePath = pOutPath; ctx->vi[i].s32loopCount = s32loopCnt; SAMPLE_COMM_VI_CreateChn(&ctx->vi[i]); pthread_create(&vi_thread_id[i], 0, vi_get_stream, (void *)(&ctx->vi[i])); } printf("%s initial finish\n", __func__); while (!quit) { sleep(1); } printf("%s exit!\n", __func__); for (i = 0; i < s32CamNum; i++) { pthread_join(vi_thread_id[i], NULL); } // Destroy VI for (i = 0; i < s32CamNum; i++) { SAMPLE_COMM_VI_DestroyChn(&ctx->vi[i]); } __FAILED: RK_MPI_SYS_Exit(); if (iq_file_dir) { #if (defined RKAIQ) && (defined UAPI2) SAMPLE_COMM_ISP_CamGroup_Stop(0); #endif } __FAILED2: if (ctx) { free(ctx); ctx = RK_NULL; } return 0; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* End of #ifdef __cplusplus */