sdk-hwV1.3/external/eyesee-mpp/dragonboard/apps/DragonBoard/testcase/votester/sample_virvi2vo.c

1070 lines
36 KiB
C
Executable File

//#define LOG_NDEBUG 0
#define LOG_TAG "sample_virvi2vo"
#include <utils/plat_log.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/mman.h>
// #include <unistd.h>
// #include <stdio.h>
// #include <stdlib.h>
// #include <fcntl.h>
// #include <string.h>
#include <sys/ioctl.h>
// #include <arpa/inet.h>
// #include <errno.h>
#include "media/mm_comm_vi.h"
#include "media/mpi_vi.h"
#include "vo/hwdisplay.h"
#include "log/log_wrapper.h"
#include <ClockCompPortIndex.h>
#include <mpi_videoformat_conversion.h>
#include <confparser.h>
#include "sample_virvi2vo_config.h"
#include "sample_virvi2vo.h"
#include "mpi_isp.h"
#include <dragonboard/dragonboard.h>
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;i<VIPP2VO_NUM;i++)
{
LoadVIPP2VOConfig(i, &pConfig->mVIPP2VOConfigArray[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;i<VIPP2VO_NUM;i++)
{
alogd("vipp[%d]: captureSize[%dx%d], displayArea[%d,%d,%dx%d]",
pConfig->mVIPP2VOConfigArray[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; i<w*h; i++)
{
if(i < w*h/2)
{
*add = 0x7F00FF00;
}
else
{
*add = 0x7F0000FF;
}
add++;
}
// void *args[2];
// void *dirty_rect_vir_addr_begin = (mem_start + pitch*y + bytes_per_pixel*x);
// void *dirty_rect_vir_addr_end = (mem_start + pitch * (y+ h));
// args[0] = dirty_rect_vir_addr_begin;
// args[1] = dirty_rect_vir_addr_end;
// ret = ioctl(pContext->mFbDev.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; i<nFrameBufLen/4; i++)
{
if(i<nFrameBufLen/8)
{
*add = 0x5fff0000;
}
else
{
*add = 0x5f0000ff;
}
add++;
}
return 0;
}
int CreateTestUILayer(SampleVIRVI2VOContext *pContext)
{
int result = 0;
//test other ui layer
ERRORTYPE ret;
pContext->mTestUILayer = 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<VIPP2VO_NUM;i++)
{
result = CreateVIPP2VOLink(i, &stContext);
if (result)
{
goto sys_init_err;
}
}
#if ISP_RUN
result = AW_MPI_ISP_SwitchIspConfig(stContext.mIspDev, stContext.mConfigPara.mIspWdrSetting);
if(result != SUCCESS)
{
aloge("fatal error! isp switch wdr[%d] fail[%d]", stContext.mConfigPara.mIspWdrSetting, result);
}
#endif
if(stContext.mConfigPara.mbAddUILayer)
{
CreateTestUILayer(&stContext);
}
if(stContext.mConfigPara.mTestDuration > 0)
{
cdx_sem_down_timedwait(&stContext.mSemExit, stContext.mConfigPara.mTestDuration*1000);
}
else
{
cdx_sem_down(&stContext.mSemExit);
}
for(i=0;i<VIPP2VO_NUM;i++)
{
DestroyVIPP2VOLink(i, &stContext);
}
if(stContext.mConfigPara.mbAddUILayer)
{
DestroyTestUILayer(&stContext);
}
AW_MPI_VO_CloseVideoLayer(stContext.mUILayer);
AW_MPI_VO_RemoveOutsideVideoLayer(stContext.mUILayer);
/* disalbe vo dev */
AW_MPI_VO_Disable(stContext.mVoDev);
stContext.mVoDev = -1;
/* exit mpp system */
AW_MPI_SYS_Exit();
sys_init_err:
_exit:
destroySampleVIRVI2VOContext(&stContext);
int disp_fd = open("/dev/fb0", O_RDWR);
if (disp_fd < 0)
{
alogd("[%s] open fb0 fail!", LOG_TAG);
}
printf("%s", ((0 == result) ? "PASS" : "FAIL"));
return result;
}