//#define LOG_NDEBUG 0 #define LOG_TAG "sample_virvi2vo" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include // #include // #include // #include // #include #include // #include // #include #include "media/mm_comm_vi.h" #include "media/mpi_vi.h" #include "vo/hwdisplay.h" #include "log/log_wrapper.h" #include #include #include #include "sample_virvi2vo_config.h" #include "sample_virvi2vo.h" #include "mpi_isp.h" #include SampleVIRVI2VOContext *pSampleVIRVI2VOContext = NULL; int initSampleVIRVI2VOContext(SampleVIRVI2VOContext *pContext) { memset(pContext, 0, sizeof(SampleVIRVI2VOContext)); pContext->mUILayer = HLAY(2, 0); cdx_sem_init(&pContext->mSemExit, 0); return 0; } int destroySampleVIRVI2VOContext(SampleVIRVI2VOContext *pContext) { cdx_sem_deinit(&pContext->mSemExit); return 0; } static ERRORTYPE SampleVIRVI2VO_VOCallbackWrapper(void *cookie, MPP_CHN_S *pChn, MPP_EVENT_TYPE event, void *pEventData) { ERRORTYPE ret = SUCCESS; SampleVIRVI2VOContext *pContext = (SampleVIRVI2VOContext*)cookie; if(MOD_ID_VOU == pChn->mModId) { alogd("VO callback: VO Layer[%d] chn[%d] event:%d", pChn->mDevId, pChn->mChnId, event); switch(event) { case MPP_EVENT_RELEASE_VIDEO_BUFFER: { VIDEO_FRAME_INFO_S *pFrameInfo = (VIDEO_FRAME_INFO_S*)pEventData; aloge("vo layer[%d] release frame id[0x%x]!", pChn->mDevId, pFrameInfo->mId); break; } case MPP_EVENT_SET_VIDEO_SIZE: { SIZE_S *pDisplaySize = (SIZE_S*)pEventData; alogd("vo layer[%d] report video display size[%dx%d]", pChn->mDevId, pDisplaySize->Width, pDisplaySize->Height); break; } case MPP_EVENT_RENDERING_START: { alogd("vo layer[%d] report rendering start", pChn->mDevId); break; } default: { //postEventFromNative(this, event, 0, 0, pEventData); aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); ret = ERR_VO_ILLEGAL_PARAM; break; } } } else { aloge("fatal error! why modId[0x%x]?", pChn->mModId); ret = FAILURE; } return ret; } static ERRORTYPE SampleVIRVI2VO_CLOCKCallbackWrapper(void *cookie, MPP_CHN_S *pChn, MPP_EVENT_TYPE event, void *pEventData) { alogw("clock channel[%d] has some event[0x%x]", pChn->mChnId, event); return SUCCESS; } static int ParseCmdLine(int argc, char **argv, SampleVIRVI2VOCmdLineParam *pCmdLinePara) { alogd("sample_virvi2vo path:[%s], arg number is [%d]", argv[0], argc); int ret = 0; int i=1; memset(pCmdLinePara, 0, sizeof(SampleVIRVI2VOCmdLineParam)); while(i < argc) { if(!strcmp(argv[i], "-path")) { if(++i >= argc) { aloge("fatal error! use -h to learn how to set parameter!!!"); ret = -1; break; } if(strlen(argv[i]) >= MAX_FILE_PATH_SIZE) { aloge("fatal error! file path[%s] too long: [%d]>=[%d]!", argv[i], strlen(argv[i]), MAX_FILE_PATH_SIZE); } strncpy(pCmdLinePara->mConfigFilePath, argv[i], MAX_FILE_PATH_SIZE-1); pCmdLinePara->mConfigFilePath[MAX_FILE_PATH_SIZE-1] = '\0'; } else if(!strcmp(argv[i], "-h")) { printf("CmdLine param example:\n" "\t run -path /home/sample_virvi2vo.conf\n"); ret = 1; break; } else { alogd("ignore invalid CmdLine param:[%s], type -h to get how to set parameter!", argv[i]); } i++; } return ret; } static void LoadVIPP2VOConfig(int idx, VIPP2VOConfig *pVIPP2VOConfig, CONFPARSER_S *pConfParser) { if(0 == idx) { pVIPP2VOConfig->mDevNum = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DEVICE_NUMBER, 0); pVIPP2VOConfig->mCaptureWidth = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_CAPTURE_WIDTH, 0); pVIPP2VOConfig->mCaptureHeight = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_CAPTURE_HEIGHT, 0); pVIPP2VOConfig->mDisplayX = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_X, 0); pVIPP2VOConfig->mDisplayY = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_Y, 0); pVIPP2VOConfig->mDisplayWidth = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_WIDTH, 0); pVIPP2VOConfig->mDisplayHeight = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_HEIGHT, 0); pVIPP2VOConfig->mLayerNum = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_LAYER_NUM, 0); } else if(1 == idx) { pVIPP2VOConfig->mDevNum = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DEVICE_NUMBER2, 0); pVIPP2VOConfig->mCaptureWidth = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_CAPTURE_WIDTH2, 0); pVIPP2VOConfig->mCaptureHeight = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_CAPTURE_HEIGHT2, 0); pVIPP2VOConfig->mDisplayX = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_X2, 0); pVIPP2VOConfig->mDisplayY = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_Y2, 0); pVIPP2VOConfig->mDisplayWidth = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_WIDTH2, 0); pVIPP2VOConfig->mDisplayHeight = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_HEIGHT2, 0); pVIPP2VOConfig->mLayerNum = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_LAYER_NUM2, 0); } else if(2 == idx) { pVIPP2VOConfig->mDevNum = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DEVICE_NUMBER3, 0); pVIPP2VOConfig->mCaptureWidth = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_CAPTURE_WIDTH3, 0); pVIPP2VOConfig->mCaptureHeight = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_CAPTURE_HEIGHT3, 0); pVIPP2VOConfig->mDisplayX = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_X3, 0); pVIPP2VOConfig->mDisplayY = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_Y3, 0); pVIPP2VOConfig->mDisplayWidth = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_WIDTH3, 0); pVIPP2VOConfig->mDisplayHeight = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_DISPLAY_HEIGHT3, 0); pVIPP2VOConfig->mLayerNum = GetConfParaInt(pConfParser, SAMPLE_VIRVI2VO_KEY_LAYER_NUM3, 0); } else { aloge("fatal error! need add vipp[%d] config!", idx); } } static ERRORTYPE loadSampleVIRVI2VOConfig(SampleVIRVI2VOConfig *pConfig, const char *conf_path) { int ret; char *ptr; pConfig->mVIPP2VOConfigArray[0].mDevNum = 0; pConfig->mVIPP2VOConfigArray[0].mCaptureWidth = 1920; pConfig->mVIPP2VOConfigArray[0].mCaptureHeight = 1080; pConfig->mVIPP2VOConfigArray[0].mDisplayX = 0; pConfig->mVIPP2VOConfigArray[0].mDisplayY = 0; pConfig->mVIPP2VOConfigArray[0].mDisplayWidth = 640; pConfig->mVIPP2VOConfigArray[0].mDisplayHeight = 360; pConfig->mPicFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420; pConfig->mFrameRate = 60; pConfig->mTestDuration = 0; pConfig->mDispType = VO_INTF_LCD; pConfig->mDispSync = VO_OUTPUT_NTSC; pConfig->mIspWdrSetting = NORMAL_CFG; if(NULL == conf_path) { alogd("user not set config file. use default test parameter!"); return SUCCESS; } CONFPARSER_S stConfParser; ret = createConfParser(conf_path, &stConfParser); if(ret < 0) { aloge("load conf fail"); return FAILURE; } memset(pConfig, 0, sizeof(SampleVIRVI2VOConfig)); int i; for(i=0;imVIPP2VOConfigArray[i], &stConfParser); } pConfig->mbAddUILayer = (BOOL)GetConfParaInt(&stConfParser, SAMPLE_VIRVI2VO_KEY_ADD_UI_LAYER, 0); pConfig->mTestUILayer = GetConfParaInt(&stConfParser, SAMPLE_VIRVI2VO_KEY_UI_TEST_LAYER, 0); pConfig->mUIDisplayWidth = GetConfParaInt(&stConfParser, SAMPLE_VIRVI2VO_KEY_UI_DISPLAY_WIDTH, 0); pConfig->mUIDisplayHeight = GetConfParaInt(&stConfParser, SAMPLE_VIRVI2VO_KEY_UI_DISPLAY_HEIGHT, 0); char *pStrPixelFormat = (char*)GetConfParaString(&stConfParser, SAMPLE_VIRVI2VO_KEY_PIC_FORMAT, NULL); if(!strcmp(pStrPixelFormat, "yu12")) { pConfig->mPicFormat = MM_PIXEL_FORMAT_YUV_PLANAR_420; } else if(!strcmp(pStrPixelFormat, "yv12")) { pConfig->mPicFormat = MM_PIXEL_FORMAT_YVU_PLANAR_420; } else if(!strcmp(pStrPixelFormat, "nv21")) { pConfig->mPicFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420; } else if(!strcmp(pStrPixelFormat, "nv12")) { pConfig->mPicFormat = MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420; } else if(!strcmp(pStrPixelFormat, "nv21s")) { pConfig->mPicFormat = MM_PIXEL_FORMAT_AW_NV21S; } else { aloge("fatal error! conf file pic_format is [%s]?", pStrPixelFormat); pConfig->mPicFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420; } char *pStrDispType = (char*)GetConfParaString(&stConfParser, SAMPLE_VIRVI2VO_KEY_DISP_TYPE, NULL); if (!strcmp(pStrDispType, "hdmi")) { pConfig->mDispType = VO_INTF_HDMI; if (pConfig->mVIPP2VOConfigArray[0].mDisplayWidth > 1920) pConfig->mDispSync = VO_OUTPUT_3840x2160_30; else if (pConfig->mVIPP2VOConfigArray[0].mDisplayWidth > 1280) pConfig->mDispSync = VO_OUTPUT_1080P30; else pConfig->mDispSync = VO_OUTPUT_720P60; } else if (!strcmp(pStrDispType, "lcd")) { pConfig->mDispType = VO_INTF_LCD; pConfig->mDispSync = VO_OUTPUT_NTSC; } else if (!strcmp(pStrDispType, "cvbs")) { pConfig->mDispType = VO_INTF_CVBS; pConfig->mDispSync = VO_OUTPUT_NTSC; } pConfig->mFrameRate = GetConfParaInt(&stConfParser, SAMPLE_VIRVI2VO_KEY_FRAME_RATE, 0); pConfig->mTestDuration = GetConfParaInt(&stConfParser, SAMPLE_VIRVI2VO_KEY_TEST_DURATION, 0); for(i=0;imVIPP2VOConfigArray[i].mDevNum, pConfig->mVIPP2VOConfigArray[i].mCaptureWidth, pConfig->mVIPP2VOConfigArray[i].mCaptureHeight, pConfig->mVIPP2VOConfigArray[i].mDisplayX, pConfig->mVIPP2VOConfigArray[i].mDisplayY, pConfig->mVIPP2VOConfigArray[i].mDisplayWidth, pConfig->mVIPP2VOConfigArray[i].mDisplayHeight); } alogd("dispSync[%d], dispType[%d], frameRate[%d], testDuration[%d]", pConfig->mDispSync, pConfig->mDispType, pConfig->mFrameRate, pConfig->mTestDuration); destroyConfParser(&stConfParser); return SUCCESS; } typedef struct { int ae_mode; int ae_expOffset; int ae_exposure; int gain; int awb_mode; int awb_coltmp; int brightness; int contrast; int saturation; int hue; unsigned int maxexp; unsigned int minexp; int sharpness; }Test_IspParam_S; Test_IspParam_S param = {0}; void handle_exit(int signo) { alogd("user want to exit!"); FILE *isp_fp = NULL; isp_fp = fopen("./isp_config.txt","w"); if(isp_fp == NULL) { printf("open isp config file error!\n"); } else { fprintf(isp_fp, "ae_mode=%d\n", param.ae_mode); fprintf(isp_fp, "ae_expOffset=%d\n", param.ae_expOffset); fprintf(isp_fp, "ae_exposure=%d\n", param.ae_exposure); fprintf(isp_fp, "gain=%d\n", param.gain); fprintf(isp_fp, "awb_mode=%d\n", param.awb_mode); fprintf(isp_fp, "awb_coltmp=%d\n", param.awb_coltmp); fprintf(isp_fp, "brightness=%d\n", param.brightness); fprintf(isp_fp, "contrast=%d\n", param.contrast); fprintf(isp_fp, "saturation=%d\n", param.saturation); fprintf(isp_fp, "hue=%d\n", param.hue); fprintf(isp_fp, "maxexp=%d\n", (int)param.maxexp); fprintf(isp_fp, "minexp=%d\n", (int)param.minexp); fprintf(isp_fp, "sharpness=%d\n", param.sharpness); fclose(isp_fp); } if(NULL != pSampleVIRVI2VOContext) { cdx_sem_up(&pSampleVIRVI2VOContext->mSemExit); } } void print_menu(void) { printf("\n---------------------\n"); printf("Please input the num to config ISp \n"); printf("\t num 1 is the AE_mode\n\t num 2 is the AE_expOffset\n\t num 3 is the AE_exposure\n\t num 4 is the gain\n\t num 5 is AWB_MODE\n\t num 6 is GetColorTemp\n\t num 7 is AE Max Exp\n\t num 8 is AE Min Exp\n\t num 9 is HUE\n\t num 10 is the Brightness\n\t num 11 is the contrast\n\t num 12 is sattuation\n\t num 13 is Sharpness\n\t num 14 is User Region\n\t num 99 is quit\n"); printf("\n---------------------\n"); } static ERRORTYPE SampleVirvi2Vo_MPPCallback(void *cookie, MPP_CHN_S *pChn, MPP_EVENT_TYPE event, void *pEventData) { SampleVIRVI2VOContext *pContext = (SampleVIRVI2VOContext*)cookie; if(MOD_ID_VIU == pChn->mModId) { switch(event) { case MPP_EVENT_VI_TIMEOUT: { alogd("receive vi timeout. vipp:%d, chn:%d", pChn->mDevId, pChn->mChnId); break; } default: { aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); break; } } } else { aloge("fatal error! unknown event[0x%x] from channel[0x%x][0x%x][0x%x]!", event, pChn->mModId, pChn->mDevId, pChn->mChnId); } return SUCCESS; } #define ISP_RUN 1 ERRORTYPE CreateVIPP2VOLink(int idx, SampleVIRVI2VOContext *pContext) { ERRORTYPE result = SUCCESS; VIPP2VOConfig *pConfig = &pContext->mConfigPara.mVIPP2VOConfigArray[idx]; VIPP2VOLinkInfo *pLinkInfo = &pContext->mLinkInfoArray[idx]; if(0 == pConfig->mCaptureWidth || 0 == pConfig->mCaptureHeight) { alogd("do not need create link for idx[%d]", idx); return result; } /* create vi channel */ pLinkInfo->mVIDev = pConfig->mDevNum; pLinkInfo->mVIChn = 0; alogd("Vipp dev[%d] vir_chn[%d]", pLinkInfo->mVIDev, pLinkInfo->mVIChn); ERRORTYPE eRet = AW_MPI_VI_CreateVipp(pLinkInfo->mVIDev); if (eRet != SUCCESS) { aloge("fatal error! AW_MPI_VI CreateVipp:%d failed", pLinkInfo->mVIDev); result = FAILURE; goto _err0; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)pContext; cbInfo.callback = (MPPCallbackFuncType)&SampleVirvi2Vo_MPPCallback; eRet = AW_MPI_VI_RegisterCallback(pLinkInfo->mVIDev, &cbInfo); if (eRet != SUCCESS) { aloge("fatal error! vipp[%d] RegisterCallback failed", pLinkInfo->mVIDev); } VI_ATTR_S stAttr; eRet = AW_MPI_VI_GetVippAttr(pLinkInfo->mVIDev, &stAttr); if (eRet != SUCCESS) { aloge("fatal error! AW_MPI_VI GetVippAttr failed"); } memset(&stAttr, 0, sizeof(VI_ATTR_S)); stAttr.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; stAttr.memtype = V4L2_MEMORY_MMAP; stAttr.format.pixelformat = map_PIXEL_FORMAT_E_to_V4L2_PIX_FMT(pContext->mConfigPara.mPicFormat); stAttr.format.field = V4L2_FIELD_NONE; stAttr.format.colorspace = V4L2_COLORSPACE_JPEG; stAttr.format.width = pConfig->mCaptureWidth; stAttr.format.height =pConfig->mCaptureHeight; stAttr.nbufs = 5; stAttr.nplanes = 2; stAttr.drop_frame_num = 0; // drop 2 second video data, default=0 /* do not use current param, if set to 1, all this configuration will * not be used. */ if(0 == idx) { stAttr.use_current_win = 0; } else { stAttr.use_current_win = 1; } stAttr.fps = pContext->mConfigPara.mFrameRate; eRet = AW_MPI_VI_SetVippAttr(pLinkInfo->mVIDev, &stAttr); if (eRet != SUCCESS) { aloge("fatal error! AW_MPI_VI SetVippAttr:%d failed", pLinkInfo->mVIDev); } #if ISP_RUN /* open isp */ AW_MPI_ISP_Run(pContext->mIspDev); #endif eRet = AW_MPI_VI_CreateVirChn(pLinkInfo->mVIDev, pLinkInfo->mVIChn, NULL); if(eRet != SUCCESS) { aloge("fatal error! createVirChn[%d] fail!", pLinkInfo->mVIChn); } eRet = AW_MPI_VI_EnableVipp(pLinkInfo->mVIDev); if(eRet != SUCCESS) { aloge("fatal error! enableVipp fail!"); result = FAILURE; goto _err1; } #if ISP_RUN //if enable CONFIG_ENABLE_SENSOR_FLIP_OPTION, flip operations must be after stream_on. AW_MPI_VI_SetVippMirror(pLinkInfo->mVIDev, 0);//0,1 AW_MPI_VI_SetVippFlip(pLinkInfo->mVIDev, 0);//0,1 #endif /* enable vo layer */ int hlay0 = 0; /*int hwDispChn = 0; while(hlay0 < VO_MAX_LAYER_NUM) { if(SUCCESS == AW_MPI_VO_EnableVideoLayer(hlay0)) { break; } hwDispChn++; hlay0 = HLAY(hwDispChn, 0); } if(hlay0 >= VO_MAX_LAYER_NUM) { aloge("fatal error! enable video layer fail!"); }*/ hlay0 = pConfig->mLayerNum; if(SUCCESS != AW_MPI_VO_EnableVideoLayer(hlay0)) { aloge("fatal error! enable video layer[%d] fail!", hlay0); hlay0 = MM_INVALID_LAYER; pLinkInfo->mVoLayer = hlay0; result = FAILURE; goto _err1_5; } pLinkInfo->mVoLayer = hlay0; AW_MPI_VO_GetVideoLayerAttr(pLinkInfo->mVoLayer, &pLinkInfo->mLayerAttr); pLinkInfo->mLayerAttr.stDispRect.X = pConfig->mDisplayX; pLinkInfo->mLayerAttr.stDispRect.Y = pConfig->mDisplayY; pLinkInfo->mLayerAttr.stDispRect.Width = pConfig->mDisplayWidth; pLinkInfo->mLayerAttr.stDispRect.Height = pConfig->mDisplayHeight; AW_MPI_VO_SetVideoLayerAttr(pLinkInfo->mVoLayer, &pLinkInfo->mLayerAttr); AW_MPI_VO_SetVideoLayerPriority(pLinkInfo->mVoLayer, 0); /* create vo channel and clock channel. (because frame information has 'pts', there is no need clock channel now) */ BOOL bSuccessFlag = FALSE; pLinkInfo->mVOChn = 0; while(pLinkInfo->mVOChn < VO_MAX_CHN_NUM) { eRet = AW_MPI_VO_CreateChn(pLinkInfo->mVoLayer, pLinkInfo->mVOChn); if(SUCCESS == eRet) { bSuccessFlag = TRUE; alogd("create vo channel[%d] success!", pLinkInfo->mVOChn); break; } else if(ERR_VO_CHN_NOT_DISABLE == eRet) { alogd("vo channel[%d] is exist, find next!", pLinkInfo->mVOChn); pLinkInfo->mVOChn++; } else { aloge("fatal error! create vo channel[%d] ret[0x%x]!", pLinkInfo->mVOChn, eRet); break; } } if(FALSE == bSuccessFlag) { pLinkInfo->mVOChn = MM_INVALID_CHN; aloge("fatal error! create vo channel fail!"); result = FAILURE; goto _err2; } cbInfo.cookie = (void*)pContext; cbInfo.callback = (MPPCallbackFuncType)&SampleVIRVI2VO_VOCallbackWrapper; AW_MPI_VO_RegisterCallback(pLinkInfo->mVoLayer, pLinkInfo->mVOChn, &cbInfo); AW_MPI_VO_SetChnDispBufNum(pLinkInfo->mVoLayer, pLinkInfo->mVOChn, 2); /* bind clock,vo, viChn (because frame information has 'pts', there is no need to bind clock channel now) */ MPP_CHN_S VOChn = {MOD_ID_VOU, pLinkInfo->mVoLayer, pLinkInfo->mVOChn}; MPP_CHN_S VIChn = {MOD_ID_VIU, pLinkInfo->mVIDev, pLinkInfo->mVIChn}; AW_MPI_SYS_Bind(&VIChn, &VOChn); /* start vo, vi_channel. */ eRet = AW_MPI_VI_EnableVirChn(pLinkInfo->mVIDev, pLinkInfo->mVIChn); if(eRet != SUCCESS) { aloge("fatal error! enableVirChn fail!"); result = FAILURE; goto _err3; } AW_MPI_VO_StartChn(pLinkInfo->mVoLayer, pLinkInfo->mVOChn); return result; _err3: eRet = AW_MPI_SYS_UnBind(&VIChn, &VOChn); if(eRet != SUCCESS) { aloge("fatal error! ViChn && VoChn SYS_UnBind fail!"); } eRet = AW_MPI_VO_DestroyChn(pLinkInfo->mVoLayer, pLinkInfo->mVOChn); if(eRet != SUCCESS) { aloge("fatal error! Vo Disable Chn fail!"); } _err2: eRet = AW_MPI_VO_DisableVideoLayer(pLinkInfo->mVoLayer); if(eRet != SUCCESS) { aloge("fatal error! VO DisableVideoLayer fail!"); } _err1_5: eRet = AW_MPI_VI_DestroyVirChn(pLinkInfo->mVIDev, pLinkInfo->mVIChn); if(eRet != SUCCESS) { aloge("fatal error! VI DestoryVirChn fail!"); } #if ISP_RUN eRet = AW_MPI_ISP_Stop(pContext->mIspDev); if(eRet != SUCCESS) { aloge("fatal error! ISP Stop fail!"); } #endif _err1: eRet = AW_MPI_VI_DestroyVipp(pLinkInfo->mVIDev); if(eRet != SUCCESS) { aloge("fatal error! VI DestoryVipp fail!"); } _err0: return result; } ERRORTYPE DestroyVIPP2VOLink(int idx, SampleVIRVI2VOContext *pContext) { ERRORTYPE eRet; VIPP2VOConfig *pConfig = &pContext->mConfigPara.mVIPP2VOConfigArray[idx]; VIPP2VOLinkInfo *pLinkInfo = &pContext->mLinkInfoArray[idx]; if(0 == pConfig->mCaptureWidth || 0 == pConfig->mCaptureHeight) { alogd("do not need destroy link for idx[%d]", idx); return SUCCESS; } /* stop vo channel, vi channel */ eRet = AW_MPI_VO_StopChn(pLinkInfo->mVoLayer, pLinkInfo->mVOChn); if(eRet != SUCCESS) { aloge("fatal error! VO StopChn fail!"); } eRet = AW_MPI_VI_DisableVirChn(pLinkInfo->mVIDev, pLinkInfo->mVIChn); if(eRet != SUCCESS) { aloge("fatal error! VI DisableVirChn fail!"); } eRet = AW_MPI_VO_DestroyChn(pLinkInfo->mVoLayer, pLinkInfo->mVOChn); if(eRet != SUCCESS) { aloge("fatal error! VO DisableChn fail!"); } pLinkInfo->mVOChn = MM_INVALID_CHN; /* disable vo layer */ eRet = AW_MPI_VO_DisableVideoLayer(pLinkInfo->mVoLayer); if(eRet != SUCCESS) { aloge("fatal error! VO DisableChn fail!"); } pLinkInfo->mVoLayer = -1; //wait hwdisplay kernel driver processing frame buffer, must guarantee this! Then vdec can free frame buffer. usleep(50*1000); eRet = AW_MPI_VI_DestroyVirChn(pLinkInfo->mVIDev, pLinkInfo->mVIChn); if(eRet != SUCCESS) { aloge("fatal error! VI DestoryVirChn fail!"); } #if ISP_RUN eRet = AW_MPI_ISP_Stop(pContext->mIspDev); if(eRet != SUCCESS) { aloge("fatal error! VO DisableChn fail!"); } #endif eRet = AW_MPI_VI_DisableVipp(pLinkInfo->mVIDev); if(eRet != SUCCESS) { aloge("fatal error! VO DisableChn fail!"); } eRet = AW_MPI_VI_DestroyVipp(pLinkInfo->mVIDev); if(eRet != SUCCESS) { aloge("fatal error! VO DisableChn fail!"); } pLinkInfo->mVIDev = MM_INVALID_DEV; pLinkInfo->mVIChn = MM_INVALID_CHN; return SUCCESS; } int DrawFb(SampleVIRVI2VOContext *pContext) { int ret; strncpy(pContext->mFbDev.mDev, "/dev/fb0", sizeof(pContext->mFbDev.mDev)); pContext->mFbDev.mFbFd = open(pContext->mFbDev.mDev, O_RDWR); if(pContext->mFbDev.mFbFd<=0) { aloge("fatal error! fd[%d]<=0", pContext->mFbDev.mFbFd); } if (-1 == ioctl(pContext->mFbDev.mFbFd, FBIOGET_VSCREENINFO, &pContext->mFbDev.mFbVar)) { aloge("ioctl FBIOGET_VSCREENINFO fail"); return -1; } alogd("fb_var_screeninfo: [%d,%d], [%d,%d], [%d,%d], bitsPerPixel[%d], grayscale[%d]", pContext->mFbDev.mFbVar.xres, pContext->mFbDev.mFbVar.yres, pContext->mFbDev.mFbVar.xres_virtual, pContext->mFbDev.mFbVar.yres_virtual, pContext->mFbDev.mFbVar.xoffset, pContext->mFbDev.mFbVar.yoffset, pContext->mFbDev.mFbVar.bits_per_pixel, pContext->mFbDev.mFbVar.grayscale); if (-1 == ioctl(pContext->mFbDev.mFbFd, FBIOGET_FSCREENINFO, &pContext->mFbDev.mFbFix)) { aloge("ioctl FBIOGET_FSCREENINFO fail"); return -1; } alogd("fb_fix_screeninfo: smem_start[0x%x], smem_len[%ld], pageSize[%d]", pContext->mFbDev.mFbFix.smem_start, pContext->mFbDev.mFbFix.smem_len, getpagesize()); //map physics address to virtual address pContext->mFbDev.mFbMemOffset = pContext->mFbDev.mFbFix.smem_start - (pContext->mFbDev.mFbFix.smem_start&~(getpagesize() - 1)); pContext->mFbDev.mFbMem = mmap(NULL, pContext->mFbDev.mFbFix.smem_len + pContext->mFbDev.mFbMemOffset, PROT_READ | PROT_WRITE, MAP_SHARED, pContext->mFbDev.mFbFd, 0); alogd("mmap: mem:%p, offset:%ld", pContext->mFbDev.mFbMem, pContext->mFbDev.mFbMemOffset); if (MAP_FAILED == pContext->mFbDev.mFbMem) { aloge("mmap error! mem:%p offset:%ld", pContext->mFbDev.mFbMem, pContext->mFbDev.mFbMemOffset); return -1; } /* if(bpp == 18) { var.red.length = 6; var.red.offset = 12; var.red.msb_right = 0; var.green.length = 6; var.green.offset = 6; var.green.msb_right = 0; var.blue.length = 6; var.blue.offset = 0; var.blue.msb_right = 0; } var.bits_per_pixel = bpp; if(ioctl(fd,FBIOPUT_VSCREENINFO,&var)==-1) { printf("put screen2 information failure\n"); return -2; } */ char *mem_start = (char*)pContext->mFbDev.mFbMem + pContext->mFbDev.mFbMemOffset; unsigned int bytes_per_pixel = pContext->mFbDev.mFbVar.bits_per_pixel >> 3; unsigned int pitch = bytes_per_pixel * pContext->mFbDev.mFbVar.xres; int x = 0; int y = 0; int w = pContext->mFbDev.mFbVar.xres; int h = pContext->mFbDev.mFbVar.yres; int *add = (int *)((char*)pContext->mFbDev.mFbMem + pContext->mFbDev.mFbMemOffset); int i; for(i=0; imFbDev.nFbFd, FBIO_CACHE_SYNC, args); // if(ret != 0) // { // aloge("fatal error! FBIO CACHE SYNC fail[%d]", ret); // } pContext->mFbDev.mFbVar.yoffset = 0; pContext->mFbDev.mFbVar.reserved[0] = x; pContext->mFbDev.mFbVar.reserved[1] = y; pContext->mFbDev.mFbVar.reserved[2] = w; pContext->mFbDev.mFbVar.reserved[3] = h; ret = ioctl(pContext->mFbDev.mFbFd, FBIOPAN_DISPLAY, &pContext->mFbDev.mFbVar); if(ret != 0) { aloge("fatal error! FBIOPAN DISPLAY fail[%d]", ret); } munmap(pContext->mFbDev.mFbMem, pContext->mFbDev.mFbFix.smem_len + pContext->mFbDev.mFbMemOffset); pContext->mFbDev.mFbMem = NULL; if(pContext->mFbDev.mFbFd >= 0) { close(pContext->mFbDev.mFbFd); pContext->mFbDev.mFbFd = -1; } return 0; } static int fillColorToRGBFrame(VIDEO_FRAME_INFO_S *pFrameInfo) { if(pFrameInfo->VFrame.mPixelFormat != MM_PIXEL_FORMAT_RGB_8888) { aloge("fatal error! pixelFormat[0x%x] is not argb8888!", pFrameInfo->VFrame.mPixelFormat); return -1; } int nFrameBufLen = pFrameInfo->VFrame.mStride[0]; //memset(pFrameInfo->VFrame.mpVirAddr[0], 0xFF, nFrameBufLen); int *add = (int *)pFrameInfo->VFrame.mpVirAddr[0]; int i; for(i=0; imTestUILayer = pContext->mConfigPara.mTestUILayer; ret = AW_MPI_VO_EnableVideoLayer(pContext->mTestUILayer); if(ret!=SUCCESS) { aloge("fatal error! enable video layer fail"); } AW_MPI_VO_GetVideoLayerAttr(pContext->mTestUILayer, &pContext->mTestUILayerAttr); pContext->mTestUILayerAttr.stDispRect.X = 0; pContext->mTestUILayerAttr.stDispRect.Y = 0; pContext->mTestUILayerAttr.stDispRect.Width = pContext->mConfigPara.mUIDisplayWidth; pContext->mTestUILayerAttr.stDispRect.Height = pContext->mConfigPara.mUIDisplayHeight; AW_MPI_VO_SetVideoLayerAttr(pContext->mTestUILayer, &pContext->mTestUILayerAttr); //create bmp frame buffer. unsigned int nPhyAddr = 0; void *pVirtAddr = NULL; unsigned int nFrameBufLen = 0; PIXEL_FORMAT_E ePixelFormat = MM_PIXEL_FORMAT_RGB_8888; switch(ePixelFormat) { case MM_PIXEL_FORMAT_RGB_8888: nFrameBufLen = pContext->mConfigPara.mUIDisplayWidth*pContext->mConfigPara.mUIDisplayHeight*4; break; case MM_PIXEL_FORMAT_RGB_1555: case MM_PIXEL_FORMAT_RGB_565: nFrameBufLen = pContext->mConfigPara.mUIDisplayWidth*pContext->mConfigPara.mUIDisplayHeight*2; break; default: aloge("fatal error! unsupport pixel format:0x%x", ePixelFormat); break; } ret = AW_MPI_SYS_MmzAlloc_Cached(&nPhyAddr, &pVirtAddr, nFrameBufLen); if(ret!=SUCCESS) { aloge("fatal error! ion malloc fail:0x%x",ret); goto _err1; } pContext->mTestUIFrame.mId = 0x21; pContext->mTestUIFrame.VFrame.mWidth = pContext->mConfigPara.mUIDisplayWidth; pContext->mTestUIFrame.VFrame.mHeight = pContext->mConfigPara.mUIDisplayHeight; pContext->mTestUIFrame.VFrame.mField = VIDEO_FIELD_FRAME; pContext->mTestUIFrame.VFrame.mPixelFormat = ePixelFormat; pContext->mTestUIFrame.VFrame.mPhyAddr[0] = nPhyAddr; pContext->mTestUIFrame.VFrame.mpVirAddr[0] = pVirtAddr; pContext->mTestUIFrame.VFrame.mStride[0] = nFrameBufLen; pContext->mTestUIFrame.VFrame.mOffsetTop = 0; pContext->mTestUIFrame.VFrame.mOffsetBottom = pContext->mTestUIFrame.VFrame.mHeight; pContext->mTestUIFrame.VFrame.mOffsetLeft = 0; pContext->mTestUIFrame.VFrame.mOffsetRight = pContext->mTestUIFrame.VFrame.mWidth; //fill color in frame. fillColorToRGBFrame(&pContext->mTestUIFrame); //create vo channel bool bSuccessFlag = false; pContext->mTestVOChn = 0; while(pContext->mTestVOChn < VO_MAX_CHN_NUM) { ret = AW_MPI_VO_CreateChn(pContext->mTestUILayer, pContext->mTestVOChn); if(SUCCESS == ret) { bSuccessFlag = true; alogd("create vo channel[%d] success!", pContext->mTestVOChn); break; } else if(ERR_VO_CHN_NOT_DISABLE == ret) { alogd("vo channel[%d] is exist, find next!", pContext->mTestVOChn); pContext->mTestVOChn++; } else { aloge("fatal error! create vo channel[%d] ret[0x%x]!", pContext->mTestVOChn, ret); break; } } if(false == bSuccessFlag) { pContext->mTestVOChn = MM_INVALID_CHN; aloge("fatal error! create vo channel fail!"); result = -1; goto _err1; } MPPCallbackInfo cbInfo; cbInfo.cookie = (void*)pContext; cbInfo.callback = (MPPCallbackFuncType)&SampleVIRVI2VO_VOCallbackWrapper; AW_MPI_VO_RegisterCallback(pContext->mTestUILayer, pContext->mTestVOChn, &cbInfo); AW_MPI_VO_SetChnDispBufNum(pContext->mTestUILayer, pContext->mTestVOChn, 0); ret = AW_MPI_VO_StartChn(pContext->mTestUILayer, pContext->mTestVOChn); if(ret != SUCCESS) { aloge("fatal error! vo start chn fail!"); } ret = AW_MPI_VO_SendFrame(pContext->mTestUILayer, pContext->mTestVOChn, &pContext->mTestUIFrame, 0); if(ret != SUCCESS) { aloge("fatal error! send frame to vo fail!"); } return result; _err1: ret = AW_MPI_SYS_MmzFree(pContext->mTestUIFrame.VFrame.mPhyAddr[0], pContext->mTestUIFrame.VFrame.mpVirAddr[0]); if(ret != SUCCESS) { aloge("fatal error! free ion memory fail!"); } _err0: ret = AW_MPI_VO_DisableVideoLayer(pContext->mTestUILayer); if(ret != SUCCESS) { aloge("fatal error! disable video layer fail!"); } return result; } int DestroyTestUILayer(SampleVIRVI2VOContext *pContext) { ERRORTYPE ret; ret = AW_MPI_VO_StopChn(pContext->mTestUILayer, pContext->mTestVOChn); if(ret != SUCCESS) { aloge("fatal error! vo stop chn fail!"); } AW_MPI_VO_DestroyChn(pContext->mTestUILayer, pContext->mTestVOChn); ret = AW_MPI_VO_DisableVideoLayer(pContext->mTestUILayer); if(ret != SUCCESS) { aloge("fatal error! disable video layer fail!"); } //wait hwdisplay kernel driver processing frame buffer, must guarantee this! Then we can free frame buffer. usleep(50*1000); ret = AW_MPI_SYS_MmzFree(pContext->mTestUIFrame.VFrame.mPhyAddr[0], pContext->mTestUIFrame.VFrame.mpVirAddr[0]); if(ret != SUCCESS) { aloge("fatal error! free ion memory fail!"); } return 0; } int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) { int result = 0; SampleVIRVI2VOContext stContext; alogd("sample_virvi2vo running!\n"); initSampleVIRVI2VOContext(&stContext); pSampleVIRVI2VOContext = &stContext; /* parse command line param */ if(ParseCmdLine(argc, argv, &stContext.mCmdLinePara) != 0) { //aloge("fatal error! command line param is wrong, exit!"); result = -1; goto _exit; } char *pConfigFilePath; if(strlen(stContext.mCmdLinePara.mConfigFilePath) > 0) { pConfigFilePath = stContext.mCmdLinePara.mConfigFilePath; } else { pConfigFilePath = NULL; } if(loadSampleVIRVI2VOConfig(&stContext.mConfigPara, pConfigFilePath) != SUCCESS) { aloge("fatal error! no config file or parse conf file fail"); result = -1; goto _exit; } /* register process function for SIGINT, to exit program. */ if (signal(SIGINT, handle_exit) == SIG_ERR) perror("can't catch SIGSEGV"); /* init mpp system */ memset(&stContext.mSysConf, 0, sizeof(MPP_SYS_CONF_S)); stContext.mSysConf.nAlignWidth = 32; AW_MPI_SYS_SetConf(&stContext.mSysConf); result = AW_MPI_SYS_Init(); if (result) { aloge("fatal error! AW_MPI_SYS_Init failed"); goto sys_init_err; } stContext.mIspDev = 0; /* enable vo dev */ stContext.mVoDev = 0; AW_MPI_VO_Enable(stContext.mVoDev); AW_MPI_VO_AddOutsideVideoLayer(stContext.mUILayer); AW_MPI_VO_CloseVideoLayer(stContext.mUILayer); /* close ui layer. */ VO_PUB_ATTR_S spPubAttr; AW_MPI_VO_GetPubAttr(stContext.mVoDev, &spPubAttr); spPubAttr.enIntfType = stContext.mConfigPara.mDispType; spPubAttr.enIntfSync = stContext.mConfigPara.mDispSync; AW_MPI_VO_SetPubAttr(stContext.mVoDev, &spPubAttr); int i; for(i=0;i 0) { cdx_sem_down_timedwait(&stContext.mSemExit, stContext.mConfigPara.mTestDuration*1000); } else { cdx_sem_down(&stContext.mSemExit); } for(i=0;i