/* * Copyright 2020 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance: 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 "rk_mpi_avs.h" #include "rk_mpi_cal.h" #include "rk_mpi_mb.h" #include "rk_mpi_mmz.h" #include "rk_mpi_venc.h" #include "rk_mpi_vpss.h" #include "rk_mpi_vo.h" #include "rk_mpi_sys.h" #include "test_common.h" #include "test_comm_argparse.h" #include "test_comm_avs.h" #include "test_comm_vpss.h" #include "test_comm_sys.h" #include "test_comm_utils.h" /* for RK3588 */ #define RK3588_VO_DEV_HDMI 0 #define RK3588_VO_DEV_MIPI 3 static RK_BOOL bExit = RK_FALSE; typedef struct rkVPSS_CFG_S { VPSS_GRP VpssGrp; RK_U32 u32VpssChnCnt; VPSS_GRP_ATTR_S stGrpVpssAttr; VPSS_CHN_ATTR_S stVpssChnAttr[VPSS_MAX_CHN_NUM]; } VPSS_CFG_S; typedef struct rkVENC_CFG_S { VENC_CHN VencChn; VENC_CHN_ATTR_S stAttr; } VENC_CFG_S; typedef struct _rkVO_CFG_S { VO_DEV s32DevId; VO_CHN s32ChnId; VO_LAYER s32LayerId; VO_VIDEO_LAYER_ATTR_S stVoLayerAttr; VO_CHN_ATTR_S stVoChnAttr; VO_CSC_S stVoCscAttr; } VO_CFG_S; static RK_S32 create_venc(VENC_CFG_S *ctx) { RK_S32 s32Ret = RK_SUCCESS; VENC_RECV_PIC_PARAM_S stRecvParam; memset(&stRecvParam, 0, sizeof(VENC_RECV_PIC_PARAM_S)); stRecvParam.s32RecvPicNum = -1; s32Ret = RK_MPI_VENC_CreateChn(ctx->VencChn, &ctx->stAttr); if (s32Ret != RK_SUCCESS) { RK_LOGE("venc [%d] RK_MPI_VENC_CreateChn failed: %#x!", ctx->VencChn, s32Ret); return s32Ret; } RK_LOGV("venc [%d] RK_MPI_VENC_CreateChn already.", ctx->VencChn); s32Ret = RK_MPI_VENC_StartRecvFrame(ctx->VencChn, &stRecvParam); if (s32Ret != RK_SUCCESS) { RK_LOGE("venc [%d] RK_MPI_VENC_StartRecvFrame failed: %#x!", ctx->VencChn, s32Ret); return s32Ret; } RK_LOGV("venc [%d] RK_MPI_VENC_StartRecvFrame already.", ctx->VencChn); return RK_SUCCESS; } static RK_S32 destroy_venc(VENC_CFG_S *ctx) { RK_S32 s32Ret = RK_SUCCESS; s32Ret = RK_MPI_VENC_StopRecvFrame(ctx->VencChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("venc [%d] RK_MPI_VENC_StopRecvFrame failed: %#x!", ctx->VencChn, s32Ret); return s32Ret; } RK_LOGV("venc [%d] RK_MPI_VENC_StopRecvFrame already.", ctx->VencChn); s32Ret = RK_MPI_VENC_DestroyChn(ctx->VencChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("venc [%d] RK_MPI_VENC_DestroyChn failed: %#x!", ctx->VencChn, s32Ret); return s32Ret; } RK_LOGV("venc [%d] RK_MPI_VENC_DestroyChn already.", ctx->VencChn); return RK_SUCCESS; } static RK_S32 create_vo(VO_CFG_S *ctx) { RK_S32 s32Ret = RK_SUCCESS; RK_U32 u32DispBufLen; VO_PUB_ATTR_S VoPubAttr; VO_LAYER VoLayer = ctx->s32LayerId; VO_DEV VoDev = ctx->s32DevId; VO_CHN VoChn = ctx->s32ChnId; memset(&VoPubAttr, 0, sizeof(VO_PUB_ATTR_S)); s32Ret = RK_MPI_VO_GetPubAttr(VoDev, &VoPubAttr); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_GetPubAttr failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_GetPubAttr already.", VoDev, VoLayer, VoChn); if (RK3588_VO_DEV_HDMI == VoDev) { VoPubAttr.enIntfType = VO_INTF_HDMI; VoPubAttr.enIntfSync = VO_OUTPUT_1080P60; } else if (RK3588_VO_DEV_MIPI == VoDev) { VoPubAttr.enIntfType = VO_INTF_MIPI; VoPubAttr.enIntfSync = VO_OUTPUT_DEFAULT; } s32Ret = RK_MPI_VO_SetPubAttr(VoDev, &VoPubAttr); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_GetPubAttr failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_SetPubAttr already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_Enable(VoDev); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_Enable failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_Enable already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_GetLayerDispBufLen(VoLayer, &u32DispBufLen); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_GetLayerDispBufLen failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_GetLayerDispBufLen already.", VoDev, VoLayer, VoChn); u32DispBufLen = 3; s32Ret = RK_MPI_VO_SetLayerDispBufLen(VoLayer, u32DispBufLen); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_GetLayerDispBufLen %d failed: %#x!", VoDev, VoLayer, VoChn, u32DispBufLen, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_GetLayerDispBufLen %d already.", VoDev, VoLayer, VoChn, u32DispBufLen); s32Ret = RK_MPI_VO_BindLayer(VoLayer, VoDev, VO_LAYER_MODE_GRAPHIC); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_BindLayer failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_BindLayer already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_SetLayerAttr(VoLayer, &ctx->stVoLayerAttr); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_SetLayerAttr failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_SetLayerAttr already.", VoDev, VoLayer, VoChn); #if VO_RGA s32Ret = RK_MPI_VO_SetLayerSpliceMode(VoLayer, VO_SPLICE_MODE_RGA); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_VO_SetLayerSpliceMode failed: %#x", s32Ret); return RK_FAILURE; } #endif s32Ret = RK_MPI_VO_EnableLayer(VoLayer); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_EnableLayer failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_EnableLayer already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_SetChnAttr(VoLayer, VoChn, &ctx->stVoChnAttr); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_SetChnAttr failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_SetChnAttr already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_SetLayerCSC(VoLayer, &ctx->stVoCscAttr); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_SetChnAttr failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_SetChnAttr already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_EnableChn(VoLayer, VoChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_EnableChn failed: %#x!", VoDev, VoLayer, VoChn, s32Ret); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_EnableChn already.", VoDev, VoLayer, VoChn); return s32Ret; } static RK_S32 destroy_vo(VO_CFG_S *ctx) { RK_S32 s32Ret = RK_SUCCESS; VO_LAYER VoLayer = ctx->s32LayerId; VO_DEV VoDev = ctx->s32DevId; VO_CHN VoChn = ctx->s32ChnId; s32Ret = RK_MPI_VO_DisableChn(VoDev, VoChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_DisableChn failed: %#x!", VoDev, VoLayer, VoChn); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_DisableChn already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_DisableLayer(VoLayer); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_DisableLayer failed: %#x!", VoDev, VoLayer, VoChn); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_DisableLayer already.", VoDev, VoLayer, VoChn); s32Ret = RK_MPI_VO_Disable(VoDev); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] RK_MPI_VO_Disable failed: %#x!", VoDev, VoLayer, VoChn); return s32Ret; } RK_LOGV("vo [%d, %d, %d] RK_MPI_VO_Disable already.", VoDev, VoLayer, VoChn); return s32Ret; } static RK_S32 test_single_avs_loop(TEST_AVS_CTX_S *ctx) { RK_S32 s32Ret = RK_SUCCESS; s32Ret = TEST_AVS_UnitTest(ctx); if (s32Ret != RK_SUCCESS) { RK_LOGE("TEST_AVS_UnitTest failed: %#x!", s32Ret); goto __FAILED; } __FAILED: return s32Ret; } static RK_VOID sigterm_handler(int sig) { RK_PRINT("signal %d\n", sig); bExit = RK_TRUE; } static RK_S32 test_avs_vpss_venc_loop(TEST_AVS_CTX_S *pstAvsCtx) { RK_PRINT(" Media link: \n"); RK_PRINT(" %d pool -> avs -> vpss -> venc(H264) \n", pstAvsCtx->s32PipeNum); RK_PRINT(" -> venc(H265) \n"); RK_S32 s32Ret = RK_SUCCESS; RK_S32 loopCount = 0; RK_S32 vpssChnCnt = 1; RK_S32 vencChnCnt = vpssChnCnt; RK_S32 vpssOutputWidth[vpssChnCnt] = {3840}; RK_S32 vpssOutputHeight[vpssChnCnt] = {2160}; VPSS_CFG_S pstVpssCtx; VENC_CFG_S *pstVencCtx; VIDEO_FRAME_INFO_S **pstPipeFrames; pstVencCtx = reinterpret_cast (malloc(sizeof(VENC_CFG_S) * vencChnCnt)); memset(pstVencCtx, 0, sizeof(VENC_CFG_S) * vencChnCnt); pstPipeFrames = reinterpret_cast( malloc(sizeof(VIDEO_FRAME_INFO_S *) * AVS_PIPE_NUM)); for (RK_S32 i = 0; i < AVS_PIPE_NUM; i++) { pstPipeFrames[i] = reinterpret_cast(malloc(sizeof(VIDEO_FRAME_INFO_S))); memset(pstPipeFrames[i], 0, sizeof(VIDEO_FRAME_INFO_S)); } s32Ret = TEST_AVS_ModCreateFramePool(pstAvsCtx); if (s32Ret != RK_SUCCESS) { goto __FREE_PIPE_FRAME; } /* avs create */ s32Ret = TEST_AVS_ModInit(pstAvsCtx); if (s32Ret != RK_SUCCESS) { goto __DESTROY_FRAME_POOL; } /* vpss config init */ pstVpssCtx.VpssGrp = 0; pstVpssCtx.u32VpssChnCnt = vpssChnCnt; pstVpssCtx.stGrpVpssAttr.u32MaxW = 8192; pstVpssCtx.stGrpVpssAttr.u32MaxH = 8192; pstVpssCtx.stGrpVpssAttr.enPixelFormat = RK_FMT_YUV420SP; pstVpssCtx.stGrpVpssAttr.stFrameRate.s32SrcFrameRate = -1; pstVpssCtx.stGrpVpssAttr.stFrameRate.s32DstFrameRate = -1; pstVpssCtx.stGrpVpssAttr.enCompressMode = COMPRESS_MODE_NONE; for (RK_S32 i = 0; i < vpssChnCnt; i ++) { pstVpssCtx.stVpssChnAttr[i].enChnMode = VPSS_CHN_MODE_USER; pstVpssCtx.stVpssChnAttr[i].enDynamicRange = DYNAMIC_RANGE_SDR8; pstVpssCtx.stVpssChnAttr[i].enPixelFormat = RK_FMT_YUV420SP; pstVpssCtx.stVpssChnAttr[i].stFrameRate.s32SrcFrameRate = -1; pstVpssCtx.stVpssChnAttr[i].stFrameRate.s32DstFrameRate = -1; pstVpssCtx.stVpssChnAttr[i].u32Width = vpssOutputWidth[i]; pstVpssCtx.stVpssChnAttr[i].u32Height = vpssOutputHeight[i]; pstVpssCtx.stVpssChnAttr[i].enCompressMode = COMPRESS_AFBC_16x16; pstVpssCtx.stVpssChnAttr[i].u32FrameBufCnt = 3; pstVpssCtx.stVpssChnAttr[i].u32Depth = 1; } /* vpss create */ s32Ret = TEST_VPSS_Start(pstVpssCtx.VpssGrp, pstVpssCtx.u32VpssChnCnt, &pstVpssCtx.stGrpVpssAttr, pstVpssCtx.stVpssChnAttr); if (s32Ret != RK_SUCCESS) { goto __DESTROY_AVS; } for (RK_S32 i = 0; i < vencChnCnt; i++) { /* venc config init */ PIC_BUF_ATTR_S stPicBufAttr; MB_PIC_CAL_S stMbPicCalResult; stPicBufAttr.u32Width = vpssOutputWidth[i]; stPicBufAttr.u32Height = vpssOutputHeight[i]; stPicBufAttr.enCompMode = COMPRESS_AFBC_16x16; stPicBufAttr.enPixelFormat = RK_FMT_YUV420SP; s32Ret = RK_MPI_CAL_VGS_GetPicBufferSize(&stPicBufAttr, &stMbPicCalResult); if (s32Ret != RK_SUCCESS) { RK_LOGE("get picture buffer size failed: %#x!", s32Ret); goto __DESTROY_VENC; } pstVencCtx[i].VencChn = i; pstVencCtx[i].stAttr.stVencAttr.enPixelFormat = RK_FMT_YUV420SP; pstVencCtx[i].stAttr.stVencAttr.u32PicWidth = vpssOutputWidth[i]; pstVencCtx[i].stAttr.stVencAttr.u32PicHeight = vpssOutputHeight[i]; pstVencCtx[i].stAttr.stVencAttr.u32VirWidth = vpssOutputWidth[i]; pstVencCtx[i].stAttr.stVencAttr.u32VirHeight = vpssOutputHeight[i]; pstVencCtx[i].stAttr.stVencAttr.u32StreamBufCnt = 3; pstVencCtx[i].stAttr.stVencAttr.u32BufSize = stMbPicCalResult.u32MBSize; if (i % 2 == 0) { pstVencCtx[i].stAttr.stVencAttr.enType = RK_VIDEO_ID_AVC; pstVencCtx[i].stAttr.stVencAttr.u32Profile = H264E_PROFILE_HIGH; pstVencCtx[i].stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; pstVencCtx[i].stAttr.stRcAttr.stH264Cbr.u32Gop = 60; pstVencCtx[i].stAttr.stRcAttr.stH264Cbr.u32BitRate = 65536; } else { pstVencCtx[i].stAttr.stVencAttr.enType = RK_VIDEO_ID_HEVC; pstVencCtx[i].stAttr.stVencAttr.u32Profile = H265E_PROFILE_MAIN; pstVencCtx[i].stAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR; pstVencCtx[i].stAttr.stRcAttr.stH265Cbr.u32Gop = 60; pstVencCtx[i].stAttr.stRcAttr.stH264Cbr.u32BitRate = 16384; } /* venc create */ s32Ret = create_venc(&pstVencCtx[i]); if (s32Ret != RK_SUCCESS) { goto __DESTROY_VENC; } } /* bind avs -> vpss */ s32Ret = TEST_SYS_AvsBindVpss(0, 0, pstVpssCtx.VpssGrp); if (s32Ret != RK_SUCCESS) { RK_LOGE("bind failed: %x, avs [%d, %d] -> vpss [%d]", s32Ret, 0, 0, pstVpssCtx.VpssGrp); goto __DESTROY_VENC; } RK_LOGV("bind success, avs [%d, %d] -> vpss [%d]", 0, 0, pstVpssCtx.VpssGrp); /* bind vpss -> venc */ for (RK_S32 i = 0; i < vpssChnCnt; i++) { s32Ret = TEST_SYS_VpssBindVenc(0, i, i); if (s32Ret != RK_SUCCESS) { RK_LOGE("bind failed: %x, vpss [%d, %d] -> venc [%d]", s32Ret, 0, i, i); goto __UNBIND_AVS_VPSS; } RK_LOGV("bind success, vpss [%d, %d] -> venc [%d]", 0, i, i); } /* thread: do somethings */ signal(SIGINT, sigterm_handler); if (pstAvsCtx->s32LoopCount > 0) { VENC_STREAM_S stVencStream; stVencStream.pstPack = reinterpret_cast(malloc(sizeof(VENC_PACK_S))); while (!bExit && loopCount < pstAvsCtx->s32LoopCount) { s32Ret = TEST_AVS_ModGetFrameFromPool(pstAvsCtx, pstPipeFrames); s32Ret = TEST_AVS_ModSendFrame(pstAvsCtx->s32GrpIndex, pstAvsCtx->s32PipeNum, pstPipeFrames); if (s32Ret != RK_SUCCESS) { TEST_AVS_ModReleaseFrameToPool(pstAvsCtx, pstPipeFrames); continue; } TEST_AVS_ModReleaseFrameToPool(pstAvsCtx, pstPipeFrames); for (RK_S32 i = 0; i < vencChnCnt; i++) { s32Ret = RK_MPI_VENC_GetStream(i, &stVencStream, 100); if (s32Ret >= 0) { RK_MPI_VENC_ReleaseStream(i, &stVencStream); } } usleep(33 * 1000); loopCount++; } if (stVencStream.pstPack) { free(stVencStream.pstPack); } } __UNBIND_VPSS_VENC: /* unbind avs -> vpss */ s32Ret = TEST_SYS_AvsUnbindVpss(0, 0, pstVpssCtx.VpssGrp); if (s32Ret != RK_SUCCESS) { RK_LOGE("unbind failed: %x, avs [%d, %d] -> vpss [%d]", s32Ret, 0, 0, pstVpssCtx.VpssGrp); } RK_LOGV("unbind success, avs [%d, %d] -> vpss [%d]", 0 , 0, pstVpssCtx.VpssGrp); __UNBIND_AVS_VPSS: /* unbind vpss -> venc */ for (RK_S32 i = 0; i < vpssChnCnt; i++) { s32Ret = TEST_SYS_VpssUnbindVenc(0, i, i); if (s32Ret != RK_SUCCESS) { RK_LOGE("unbind failed: %x, vpss [%d, %d] -> venc [%d]", s32Ret, pstVpssCtx.VpssGrp, i, i); } RK_LOGV("unbind success, vpss [%d, %d] -> venc [%d]", pstVpssCtx.VpssGrp, i, i); } __DESTROY_VENC: /* destroy venc */ for (RK_S32 i = 0; i < vencChnCnt; i++) { s32Ret = destroy_venc(&pstVencCtx[i]); if (s32Ret != RK_SUCCESS) { RK_LOGE("venc [%d] destroy_venc failed: %#x", i, s32Ret); } RK_LOGV("venc [%d] destroy_venc already.", i); } __DESTROY_VPSS: /* destroy vpss */ s32Ret = TEST_VPSS_Stop(pstVpssCtx.VpssGrp, pstVpssCtx.u32VpssChnCnt); if (s32Ret != RK_SUCCESS) { RK_LOGE("vpss [%d] TEST_VPSS_Stop failed: %#x", pstVpssCtx.VpssGrp, s32Ret); } RK_LOGV("vpss [%d] TEST_VPSS_Stop already.", pstVpssCtx.VpssGrp); __DESTROY_AVS: /* destroy avs */ s32Ret = TEST_AVS_ModDeInit(pstAvsCtx); if (s32Ret != RK_SUCCESS) { RK_LOGE("avs [%d] TEST_AVS_ModDeInit failed: %#x", pstAvsCtx->s32GrpIndex, s32Ret); } RK_LOGV("avs [%d] TEST_AVS_ModDeInit already.", pstAvsCtx->s32GrpIndex); __DESTROY_FRAME_POOL: s32Ret = TEST_AVS_ModDestroyFramePool(pstAvsCtx); if (s32Ret != RK_SUCCESS) { RK_LOGE("avs [%d] TEST_AVS_ModDestroyFramePool failed: %#x", pstAvsCtx->s32GrpIndex, s32Ret); } RK_LOGV("avs [%d] TEST_AVS_ModDestroyFramePool already.", pstAvsCtx->s32GrpIndex); __FREE_PIPE_FRAME: for (RK_S32 i = 0; i < AVS_PIPE_NUM; i++) { RK_SAFE_FREE(pstPipeFrames[i]); } RK_SAFE_FREE(pstPipeFrames); __FREE_VENC_CFG: RK_SAFE_FREE(pstVencCtx); return s32Ret; } static RK_S32 test_avs_vo_loop(TEST_AVS_CTX_S *pstAvsCtx) { RK_PRINT(" Media link: \n"); RK_PRINT(" %d avs -> vo (HDMI) \n", pstAvsCtx->s32PipeNum); RK_S32 s32Ret = RK_SUCCESS; RK_S32 loopCount = 0; VO_CFG_S pstVoCtx; VIDEO_FRAME_INFO_S **pstPipeFrames; pstPipeFrames = reinterpret_cast( malloc(sizeof(VIDEO_FRAME_INFO_S *) * AVS_PIPE_NUM)); for (RK_S32 i = 0; i < AVS_PIPE_NUM; i++) { pstPipeFrames[i] = reinterpret_cast(malloc(sizeof(VIDEO_FRAME_INFO_S))); memset(pstPipeFrames[i], 0, sizeof(VIDEO_FRAME_INFO_S)); } s32Ret = TEST_AVS_ModCreateFramePool(pstAvsCtx); if (s32Ret != RK_SUCCESS) { goto __FREE_PIPE_FRAME; } /* avs create */ s32Ret = TEST_AVS_ModInit(pstAvsCtx); if (s32Ret != RK_SUCCESS) { goto __DESTROY_FRAME_POOL; } /* vo config init */ pstVoCtx.s32LayerId = 0; pstVoCtx.s32DevId = RK3588_VO_DEV_HDMI; if (RK3588_VO_DEV_HDMI == pstVoCtx.s32DevId) { pstVoCtx.stVoLayerAttr.stDispRect.u32Width = 1920; pstVoCtx.stVoLayerAttr.stDispRect.u32Height = 1080; } else if (RK3588_VO_DEV_MIPI == pstVoCtx.s32DevId) { pstVoCtx.stVoLayerAttr.stDispRect.u32Width = 1080; pstVoCtx.stVoLayerAttr.stDispRect.u32Height = 1920; } pstVoCtx.stVoLayerAttr.enPixFormat = RK_FMT_RGB888; pstVoCtx.s32ChnId = 0; pstVoCtx.stVoCscAttr.enCscMatrix = VO_CSC_MATRIX_IDENTITY; pstVoCtx.stVoCscAttr.u32Contrast = 50; pstVoCtx.stVoCscAttr.u32Hue = 50; pstVoCtx.stVoCscAttr.u32Luma = 50; pstVoCtx.stVoCscAttr.u32Satuature = 50; pstVoCtx.stVoLayerAttr.stDispRect.s32X = 0; pstVoCtx.stVoLayerAttr.stDispRect.s32Y = 0; pstVoCtx.stVoLayerAttr.stImageSize.u32Width = pstVoCtx.stVoLayerAttr.stDispRect.u32Width; pstVoCtx.stVoLayerAttr.stImageSize.u32Height = pstVoCtx.stVoLayerAttr.stDispRect.u32Height; pstVoCtx.stVoLayerAttr.u32DispFrmRt = 30; pstVoCtx.stVoChnAttr.stRect.s32X = 0; pstVoCtx.stVoChnAttr.stRect.s32Y = 0; pstVoCtx.stVoChnAttr.stRect.u32Width = pstVoCtx.stVoLayerAttr.stImageSize.u32Width; pstVoCtx.stVoChnAttr.stRect.u32Height = pstVoCtx.stVoLayerAttr.stImageSize.u32Height; pstVoCtx.stVoChnAttr.bDeflicker = RK_FALSE; pstVoCtx.stVoChnAttr.u32Priority = 1; pstVoCtx.stVoChnAttr.u32FgAlpha = 128; pstVoCtx.stVoChnAttr.u32BgAlpha = 0; /* vo creat */ s32Ret = create_vo(&pstVoCtx); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] create failed: %x", pstVoCtx.s32DevId, pstVoCtx.s32LayerId, pstVoCtx.s32ChnId, s32Ret); goto __DESTROY_AVS; } /* bind avs -> vo */ s32Ret = TEST_SYS_AvsBindVo(0, 0, 0, 0); if (s32Ret != RK_SUCCESS) { RK_LOGE("bind failed: %x, avs [%d, %d] -> vo [%d, %d]", s32Ret, 0, 0, 0, 0); goto __DESTROY_VO; } RK_LOGV("bind success, avs [%d, %d] -> vo [%d, %d]", 0 , 0, 0, 0); /* thread: do somethings */ signal(SIGINT, sigterm_handler); if (pstAvsCtx->s32LoopCount > 0) { while (!bExit && loopCount < pstAvsCtx->s32LoopCount) { s32Ret = TEST_AVS_ModGetFrameFromPool(pstAvsCtx, pstPipeFrames); s32Ret = TEST_AVS_ModSendFrame(pstAvsCtx->s32GrpIndex, pstAvsCtx->s32PipeNum, pstPipeFrames); if (s32Ret != RK_SUCCESS) { TEST_AVS_ModReleaseFrameToPool(pstAvsCtx, pstPipeFrames); continue; } TEST_AVS_ModReleaseFrameToPool(pstAvsCtx, pstPipeFrames); usleep(1000); loopCount++; } } __UNBIND_AVS_VO: /* unbind avs -> vo */ s32Ret = TEST_SYS_AvsUnbindVo(0, 0, 0, 0); if (s32Ret != RK_SUCCESS) { RK_LOGE("bind failed: %x, avs [%d, %d] -> vo [%d, %d]", s32Ret, pstAvsCtx->s32GrpIndex, 0, pstVoCtx.s32DevId, pstVoCtx.s32ChnId); } RK_LOGV("unbind success, avs [%d, %d] -> vo [%d, %d]", pstAvsCtx->s32GrpIndex, 0, pstVoCtx.s32DevId, pstVoCtx.s32ChnId); __DESTROY_VO: /* destroy vo */ s32Ret = destroy_vo(&pstVoCtx); if (s32Ret != RK_SUCCESS) { RK_LOGE("vo [%d, %d, %d] destroy_vo failed: %#x", pstVoCtx.s32DevId, pstVoCtx.s32LayerId, pstVoCtx.s32ChnId, s32Ret); } RK_LOGV("vo [%d, %d, %d] destroy_vo already.", pstVoCtx.s32DevId, pstVoCtx.s32LayerId, pstVoCtx.s32ChnId); __DESTROY_AVS: /* destroy avs */ s32Ret = TEST_AVS_ModDeInit(pstAvsCtx); if (s32Ret != RK_SUCCESS) { RK_LOGE("avs [%d] TEST_AVS_ModDeInit failed: %#x", pstAvsCtx->s32GrpIndex, s32Ret); } RK_LOGV("avs [%d] TEST_AVS_ModDeInit already.", pstAvsCtx->s32GrpIndex); __DESTROY_FRAME_POOL: s32Ret = TEST_AVS_ModDestroyFramePool(pstAvsCtx); if (s32Ret != RK_SUCCESS) { RK_LOGE("avs [%d] TEST_AVS_ModDestroyFramePool failed: %#x", pstAvsCtx->s32GrpIndex, s32Ret); } RK_LOGV("avs [%d] TEST_AVS_ModDestroyFramePool already.", pstAvsCtx->s32GrpIndex); __FREE_PIPE_FRAME: for (RK_S32 i = 0; i < AVS_PIPE_NUM; i++) { RK_SAFE_FREE(pstPipeFrames[i]); } RK_SAFE_FREE(pstPipeFrames); return s32Ret; } static const char *const usages[] = { "./rk_mpi_avs_test [--test_mode TEST_MODE] [-c COMPRESS_MODE] [-n LOOP_COUNT] [-p PIPE_NUM]", RK_NULL, }; static void mpi_avs_test_show_options(const TEST_AVS_CTX_S *ctx) { RK_PRINT("cmd parse result:\n"); RK_PRINT("input file path : %s\n", ctx->srcFilePath); RK_PRINT("output file path : %s\n", ctx->dstFilePath); RK_PRINT("test mode : %d\n", ctx->enTestMode); RK_PRINT("group number : %d\n", ctx->s32GrpNum); RK_PRINT("pipe number : %d\n", ctx->s32PipeNum); RK_PRINT("channel number : %d\n", ctx->s32ChnNum); RK_PRINT("loop count : %d\n", ctx->s32LoopCount); RK_PRINT("input width : %d\n", ctx->u32SrcWidth); RK_PRINT("input height : %d\n", ctx->u32SrcHeight); RK_PRINT("input virtual width : %d\n", ctx->u32SrcVirWidth); RK_PRINT("input virtual height : %d\n", ctx->u32SrcVirHeight); RK_PRINT("input pixel format : %d\n", ctx->enSrcPixFormat); RK_PRINT("input compress mode : %d\n", ctx->enSrcCompressMode); RK_PRINT("output width : %d\n", ctx->u32DstWidth); RK_PRINT("output height : %d\n", ctx->u32DstHeight); RK_PRINT("output pixel format : %d\n", ctx->enDstPixFormat); RK_PRINT("output compress mode : %d\n", ctx->enDstCompressMode); RK_PRINT("work mode : %d\n", ctx->enAvsWorkMode); RK_PRINT("projection mode : %d\n", ctx->enAvsProjMode); RK_PRINT("params sources : %d\n", ctx->enParamSource); RK_PRINT("lut file path : %s\n", ctx->lutFilePath); RK_PRINT("lut accuracy : %d\n", ctx->enLutAccuracy); RK_PRINT("lut fuse width : %d\n", ctx->enLutFuseWidth); RK_PRINT("lut step x : %d\n", ctx->stLutStep.enStepX); RK_PRINT("lut step y : %d\n", ctx->stLutStep.enStepY); RK_PRINT("calib file name : %s\n", ctx->calibFileName); RK_PRINT("mesh file path : %s\n", ctx->meshFilePath); RK_PRINT("avs frame sync : %d\n", ctx->bFrameSync); RK_PRINT("center x : %d\n", ctx->stCenter.s32X); RK_PRINT("center x : %d\n", ctx->stCenter.s32Y); RK_PRINT("fov x : %d\n", ctx->stFov.u32FOVX); RK_PRINT("fov y : %d\n", ctx->stFov.u32FOVY); RK_PRINT("rotation ori yaw : %d\n", ctx->stOriRotation.s32Yaw); RK_PRINT("rotation ori pitch : %d\n", ctx->stOriRotation.s32Pitch); RK_PRINT("rotation ori roll : %d\n", ctx->stOriRotation.s32Roll); RK_PRINT("rotation yaw : %d\n", ctx->stRotation.s32Yaw); RK_PRINT("rotation pitch : %d\n", ctx->stRotation.s32Pitch); RK_PRINT("rotation roll : %d\n", ctx->stRotation.s32Roll); RK_PRINT("distance : %3.2f\n", ctx->fDistance); RK_PRINT("enable comm mb pool : %d\n", ctx->bCommPool); } RK_S32 main(int argc, const char **argv) { RK_S32 s32Ret = RK_FAILURE; TEST_AVS_CTX_S ctx; memset(&ctx, 0, sizeof(TEST_AVS_CTX_S)); ctx.dstFilePath = RK_NULL; ctx.s32LoopCount = 1; ctx.enTestMode = TEST_MODE_AVS_ONLY; ctx.enParamSource = AVS_PARAM_SOURCE_CALIB; ctx.bFrameSync = RK_FALSE; ctx.enAvsWorkMode = AVS_MODE_BLEND; ctx.s32GrpNum = 1; ctx.s32ChnNum = 1; ctx.s32PipeNum = 6; ctx.s32GrpIndex = 0; ctx.u32ChnDepth = 1; ctx.u32FrameBufCnt = 3; ctx.s32SrcChnRate = -1; ctx.s32DstChnRate = -1; ctx.s32SrcGrpRate = -1; ctx.s32DstGrpRate = -1; ctx.fDistance = 1.0; RK_LOGE("avs test running enter!"); struct argparse_option options[] = { OPT_HELP(), OPT_GROUP("basic options:"), OPT_STRING('i', "input", &(ctx.srcFilePath), "input file name. e.g.(/userdata/6x_equirectangular/input_image/). default(NULL).", NULL, 0, 0), OPT_STRING('o', "output", &(ctx.dstFilePath), "output file path. e.g.(/userdata/res/). default(NULL).", NULL, 0, 0), OPT_INTEGER('\0', "test_mode", &(ctx.enTestMode), "test mode. default(0. 0: avs single mod test, 1: multi mods bind test).", NULL, 0, 0), OPT_INTEGER('n', "loop count", &(ctx.s32LoopCount), "loop running count. default(1).", NULL, 0, 0), OPT_INTEGER('g', "group_count", &(ctx.s32GrpNum), "the count of avs group. default(1).", NULL, 0, 0), OPT_INTEGER('p', "pipe_count", &(ctx.s32PipeNum), "the count of avs pipe. default(6).", NULL, 0, 0), OPT_INTEGER('c', "channel_count", &(ctx.s32ChnNum), "the count of avs channel. default(1).", NULL, 0, 0), OPT_INTEGER('w', "src_width", &(ctx.u32SrcWidth), "src width. e.g.(2560). .", NULL, 0, 0), OPT_INTEGER('h', "src_height", &(ctx.u32SrcHeight), "src height. e.g.(1520). .", NULL, 0, 0), OPT_INTEGER('\0', "src_vir_width", &(ctx.u32SrcVirWidth), "src virtual width. e.g.(2560). default(0).", NULL, 0, 0), OPT_INTEGER('\0', "src_vir_height", &(ctx.u32SrcVirHeight), "src virtual height. e.g.(1520). default(0).", NULL, 0, 0), OPT_INTEGER('f', "src_format", &(ctx.enSrcPixFormat), "src pixel format. default(only 0. 0 is NV12).", NULL, 0, 0), OPT_INTEGER('m', "src_compress", &(ctx.enSrcCompressMode), "src compress mode. default(0. 0: NONE, 1: AFBC).", NULL, 0, 0), OPT_INTEGER('W', "dst_width", &(ctx.u32DstWidth), "dst width. e.g.(8192). .", NULL, 0, 0), OPT_INTEGER('H', "dst_height", &(ctx.u32DstHeight), "dst height. e.g.(3840). .", NULL, 0, 0), OPT_INTEGER('M', "dst_compress", &(ctx.enDstCompressMode), "dst compress mode. default(0. 0: NONE, 1: AFBC).", NULL, 0, 0), OPT_INTEGER('F', "dst_format", &(ctx.enDstPixFormat), "dst pixel format. default(only 0. 0 is NV12).", NULL, 0, 0), OPT_INTEGER('\0', "work_mode", &(ctx.enAvsWorkMode), "work mode. default(0. 0: BLEND, 1: NOBLEND_VER, 2: NOBLEND_HOR, 3: NOBLEND_QR).", NULL, 0, 0), OPT_INTEGER('\0', "proj_mode", &(ctx.enAvsProjMode), "projection mode. default(0. 0: EQUIRECTANGULAR, 1: RECTILINEAR, 2: CYLINDRICAL," "3: CUBE_MAP, 4: EQUIRECTANGULAR_TRANS).", NULL, 0, 0), OPT_INTEGER('\0', "frame_sync", &(ctx.bFrameSync), "whether enable avs frame sync. default(0. 0: Disable, 1: Enable).", NULL, 0, 0), OPT_INTEGER('\0', "param_source", &(ctx.enParamSource), "params required for stitch are obtained by lut or calib. default(1. 0: Lut, 1: Calib).", NULL, 0, 0), OPT_STRING('\0', "lut_file_path", &(ctx.lutFilePath), "lut file path. e.g.(/userdata/6x_equirectangular/middle_lut/). default(NULL).", NULL, 0, 0), OPT_INTEGER('\0', "lut_accuracy", &(ctx.enLutAccuracy), "lut accuracy. default(0, 0: HIGH, 1: LOW).", NULL, 0, 0), OPT_INTEGER('\0', "lut_use_width", &(ctx.enLutFuseWidth), "lut fuse width. default(0, 0: 128 pixel, 1: 256 pixel, 2: 512 pixel).", NULL, 0, 0), OPT_INTEGER('\0', "lut_step_x", &(ctx.stLutStep.enStepX), "lut step in the x-axis direction. default(0, 0: 16 pixel, 1: 32 pixel, 2: 64 pixel).", NULL, 0, 0), OPT_INTEGER('\0', "lut_step_y", &(ctx.stLutStep.enStepY), "lut step in the y-axis direction. default(0, 0: 16 pixel, 1: 32 pixel, 2: 64 pixel).", NULL, 0, 0), OPT_STRING('\0', "calib_file_name", &(ctx.calibFileName), "calib file name. e.g.(/userdata/avs/6x_equirectangular/avs_calib/calib_file.pto). default(NULL).", NULL, 0, 0), OPT_STRING('\0', "mesh_file_path", &(ctx.meshFilePath), "mesh file path. e.g.(/userdata/avs/6x_equirectangular/avs_mesh/). default(NULL).", NULL, 0, 0), OPT_INTEGER('\0', "center_x", &(ctx.stCenter.s32X), "center point in the x-axis direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "center_y", &(ctx.stCenter.s32Y), "center point in the y-axis direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "fov_x", &(ctx.stFov.u32FOVX), "fov size in the x-axis direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "fov_y", &(ctx.stFov.u32FOVY), "fov size in the y-axis direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "ori_yaw", &(ctx.stOriRotation.s32Yaw), "ori rotation in the yaw direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "ori_pitch", &(ctx.stOriRotation.s32Pitch), "ori rotation in the pitch direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "ori_roll", &(ctx.stOriRotation.s32Roll), "ori rotation in the roll direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "yaw", &(ctx.stRotation.s32Yaw), "rotation in the yaw direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "pitch", &(ctx.stRotation.s32Pitch), "rotation in the pitch direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "distance", &(ctx.fDistance), "optimal stitch distance. default(1.0).", NULL, 0, 0), OPT_INTEGER('\0', "src_grp_rate", &(ctx.s32SrcGrpRate), "src avs group frame rate, default(-1).", NULL, 0, 0), OPT_INTEGER('\0', "dst_grp_rate", &(ctx.s32DstGrpRate), "dst avs group frame rate, default(-1).", NULL, 0, 0), OPT_INTEGER('d', "chn_depth", &(ctx.u32ChnDepth), "channel output depth, default(3)", NULL, 0, 0), OPT_INTEGER('b', "chn_buf_cnt", &(ctx.u32FrameBufCnt), "channel output buf cnt, default(3)", NULL, 0, 0), OPT_INTEGER('\0', "roll", &(ctx.stRotation.s32Roll), "rotation in the roll direction. default(0).", NULL, 0, 0), OPT_INTEGER('\0', "src_chn_rate", &(ctx.s32SrcChnRate), "src avs channel frame rate, default(-1).", NULL, 0, 0), OPT_INTEGER('\0', "dst_chn_rate", &(ctx.s32DstChnRate), "dst avs channel frame rate, default(-1).", NULL, 0, 0), OPT_BOOLEAN('\0', "comm_mb_pool", &(ctx.bCommPool), "whether enable common mb pool, default(0, 0: Disable, 1: Enable).", NULL, 0, 0), OPT_GROUP("external options:"), OPT_BOOLEAN('\0', "get_final_lut", &(ctx.bGetFinalLut), "whether get final lut, default(0, 0: Disable, 1: Enable).", NULL, 0, 0), OPT_END(), }; struct argparse argparse; argparse_init(&argparse, options, usages, 0); argparse_describe(&argparse, "\nselect a test case to run.", "\nuse --help for details."); argc = argparse_parse(&argparse, argc, argv); mpi_avs_test_show_options(&ctx); if (ctx.u32SrcWidth <= 0 || ctx.u32SrcHeight <= 0 || ctx.u32DstWidth <= 0 || ctx.u32DstHeight <= 0) { argparse_usage(&argparse); return RK_FAILURE; } s32Ret = RK_MPI_SYS_Init(); if (s32Ret != RK_SUCCESS) { return s32Ret; } switch (ctx.enTestMode) { case TEST_MODE_AVS_ONLY: { s32Ret = test_single_avs_loop(&ctx); if (s32Ret != RK_SUCCESS) { goto __FAILED; } } break; case TEST_MODE_AVS_VO: { s32Ret = test_avs_vo_loop(&ctx); if (s32Ret != RK_SUCCESS) { goto __FAILED; } } break; case TEST_MODE_AVS_VPSS_VENC: { s32Ret = test_avs_vpss_venc_loop(&ctx); if (s32Ret != RK_SUCCESS) { goto __FAILED; } } break; default: RK_LOGE("unsupport test mode: %d", ctx.enTestMode); break; } s32Ret = RK_MPI_SYS_Exit(); if (s32Ret != RK_SUCCESS) { return s32Ret; } RK_LOGV("test running ok."); return RK_SUCCESS; __FAILED: RK_LOGE("test running exit: %x", s32Ret); RK_MPI_SYS_Exit(); return s32Ret; }