sdk-hwV1.3/external/eyesee-mpp/dragonboard/apps/DragonBoard/testcase/csitester/sample_virvi.c

944 lines
29 KiB
C
Executable File

/******************************************************************************
Copyright (C), 2001-2017, Allwinner Tech. Co., Ltd.
******************************************************************************
File Name : sample_virvi.c
Version : Initial Draft
Author : Allwinner BU3-PD2 Team
Created : 2017/1/5
Last Modified :
Description : mpp component implement
Function List :
History :
******************************************************************************/
#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 <utils/plat_log.h>
#include "media/mpi_sys.h"
#include "media/mm_comm_vi.h"
#include "media/mpi_vi.h"
#include "media/mpi_isp.h"
#include <mpi_venc.h>
#include <utils/VIDEO_FRAME_INFO_S.h>
#include <mpi_videoformat_conversion.h>
#include <confparser.h>
#include <cdx_list.h>
#include "sample_virvi.h"
#include "sample_virvi_config.h"
#define ISP_RUN 1
#define DEFAULT_SAVE_PIC_DIR "/tmp"
SampleVirViContext *gpSampleVirViContext = NULL;
static void handle_exit()
{
alogd("user want to exit!");
if(NULL != gpSampleVirViContext)
{
cdx_sem_up(&gpSampleVirViContext->mSemExit);
}
}
static int ParseCmdLine(int argc, char **argv, SampleVirViCmdLineParam *pCmdLinePara)
{
alogd("sample virvi path:[%s], arg number is [%d]", argv[0], argc);
int ret = 0;
int i=1;
memset(pCmdLinePara, 0, sizeof(SampleVirViCmdLineParam));
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"))
{
alogd("CmdLine param:\n"
"\t-path /home/sample_virvi.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 char *parserKeyCfg(char *pKeyCfg, int nKey)
{
static char keyCfg[MAX_FILE_PATH_SIZE] = {0};
if (pKeyCfg)
{
sprintf(keyCfg, "%s_%d", pKeyCfg, nKey);
return keyCfg;
}
aloge("fatal error! key cfg is null key num[%d]", nKey);
return NULL;
}
static void judgeCaptureFormat(char *pFormatConf, PIXEL_FORMAT_E *pCapFromat)
{
if (NULL != pFormatConf)
{
if (!strcmp(pFormatConf, "nv21"))
{
*pCapFromat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
}
else if (!strcmp(pFormatConf, "yv12"))
{
*pCapFromat = MM_PIXEL_FORMAT_YVU_PLANAR_420;
}
else if (!strcmp(pFormatConf, "nv12"))
{
*pCapFromat = MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
}
else if (!strcmp(pFormatConf, "yu12"))
{
*pCapFromat = MM_PIXEL_FORMAT_YUV_PLANAR_420;
}
/* aw compression format */
else if (!strcmp(pFormatConf, "aw_afbc"))
{
*pCapFromat = MM_PIXEL_FORMAT_YUV_AW_AFBC;
}
else if (!strcmp(pFormatConf, "aw_lbc_2_0x"))
{
*pCapFromat = MM_PIXEL_FORMAT_YUV_AW_LBC_2_0X;
}
else if (!strcmp(pFormatConf, "aw_lbc_2_5x"))
{
*pCapFromat = MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X;
}
else if (!strcmp(pFormatConf, "aw_lbc_1_5x"))
{
*pCapFromat = MM_PIXEL_FORMAT_YUV_AW_LBC_1_5X;
}
else if (!strcmp(pFormatConf, "aw_lbc_1_0x"))
{
*pCapFromat = MM_PIXEL_FORMAT_YUV_AW_LBC_1_0X;
}
else if (!strcmp(pFormatConf, "srggb10"))
{
*pCapFromat = MM_PIXEL_FORMAT_RAW_SRGGB10;
}
/* aw_package_422 NOT support */
// else if (!strcmp(ptr, "aw_package_422"))
// {
// *pCapFromat = MM_PIXEL_FORMAT_YVYU_AW_PACKAGE_422;
// }
else
{
*pCapFromat = MM_PIXEL_FORMAT_YVU_PLANAR_420;
aloge("fatal error! wrong src pixfmt:%s", pFormatConf);
alogw("use the default pixfmt %d", *pCapFromat);
}
}
}
void judgeCaptureColorspace(char *pColorSpConf, enum v4l2_colorspace *pV4L2ColorSp)
{
if (NULL != pColorSpConf)
{
if (strcmp(pColorSpConf, "jpeg") == 0)
{
*pV4L2ColorSp = V4L2_COLORSPACE_JPEG;
}
else if (strcmp(pColorSpConf, "rec709") == 0)
{
*pV4L2ColorSp = V4L2_COLORSPACE_REC709;
}
else if (strcmp(pColorSpConf, "rec709_part_range") == 0)
{
*pV4L2ColorSp = V4L2_COLORSPACE_REC709_PART_RANGE;
}
else
{
aloge("fatal error! wrong color space:%s, use dafault jpeg", pColorSpConf);
*pV4L2ColorSp = V4L2_COLORSPACE_JPEG;
}
}
}
static ERRORTYPE loadConfigPara(SampleVirViContext *pContext, const char *conf_path)
{
int ret = 0;
char *ptr = NULL;
SampleVirViConfig *pConfig = NULL;
SampleVirviSaveBufMgrConfig *pSaveBufMgrConfig = &pContext->mSaveBufMgrConfig;
//default onlu use vipp0
pConfig = &pContext->mCaps[0].mConfig;
memset(pConfig, 0, sizeof(SampleVirViConfig));
pConfig->DevNum = 0;
pConfig->mIspDevNum = 0;
pConfig->FrameRate = 20;
pConfig->PicWidth = 1920;
pConfig->PicHeight = 1080;
pConfig->PicFormat = V4L2_PIX_FMT_NV21M;
pConfig->mColorSpace = V4L2_COLORSPACE_JPEG;
pConfig->mViDropFrmCnt = 0;
pConfig = &pContext->mCaps[1].mConfig;
memset(pConfig, 0, sizeof(SampleVirViConfig));
pConfig->DevNum = MM_INVALID_DEV;
pConfig->mIspDevNum = MM_INVALID_DEV;
pConfig = &pContext->mCaps[2].mConfig;
memset(pConfig, 0, sizeof(SampleVirViConfig));
pConfig->DevNum = MM_INVALID_DEV;
pConfig->mIspDevNum = MM_INVALID_DEV;
pConfig = &pContext->mCaps[3].mConfig;
memset(pConfig, 0, sizeof(SampleVirViConfig));
pConfig->DevNum = MM_INVALID_DEV;
pConfig->mIspDevNum = MM_INVALID_DEV;
memset(pSaveBufMgrConfig, 0, sizeof(SampleVirviSaveBufMgrConfig));
pSaveBufMgrConfig->mSavePicDev = 0;
pSaveBufMgrConfig->mYuvFrameCount = 5;
sprintf(pSaveBufMgrConfig->mYuvFile, "%s/test.yuv", DEFAULT_SAVE_PIC_DIR);
pSaveBufMgrConfig->mRawStoreCount = 5;
pSaveBufMgrConfig->mRawStoreInterval = 20;
sprintf(pSaveBufMgrConfig->mStoreDirectory, "%s", DEFAULT_SAVE_PIC_DIR);
pSaveBufMgrConfig->mSavePicBufferLen = 1920*1080*3/2;
pSaveBufMgrConfig->mSavePicBufferNum = 5;
if(conf_path != NULL)
{
CONFPARSER_S stConfParser;
ret = createConfParser(conf_path, &stConfParser);
if(ret < 0)
{
aloge("load conf fail");
return FAILURE;
}
for (int i = 0; i < MAX_CAPTURE_NUM; i++)
{
pConfig = &pContext->mCaps[i].mConfig;
pConfig->AutoTestCount = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Auto_Test_Count, i), 0);
pConfig->GetFrameCount = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Get_Frame_Count, i), 0);
pConfig->DevNum = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Dev_Num, i), 0);
pConfig->mIspDevNum = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Dev_Num, i), 0);
pConfig->FrameRate = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Frame_Rate, i), 0);
pConfig->PicWidth = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Pic_Width, i), 0);
pConfig->PicHeight = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Pic_Height, i), 0);
ptr = (char*)GetConfParaString(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Pic_Format, i), NULL);
judgeCaptureFormat(ptr, &pConfig->PicFormat);
ptr = (char *)GetConfParaString(&stConfParser, parserKeyCfg(SAMPLE_VirVi_COLOR_SPACE, i), NULL);
judgeCaptureColorspace(ptr, &pConfig->mColorSpace);
//alogd("srcPixFmt=%d, ColorSpace=%d", pConfig->PicFormat, pConfig->mColorSpace);
pConfig->mEnableWDRMode = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_Enable_WDR, i), 0);
pConfig->mViDropFrmCnt = GetConfParaInt(&stConfParser, parserKeyCfg(SAMPLE_VirVi_ViDropFrmCnt, i), 0);
//alogd("ViDropFrameNum: %d", pConfig->mViDropFrmCnt);
}
pSaveBufMgrConfig->mSavePicDev = GetConfParaInt(&stConfParser, SAMPLE_VirVi_SavePicDev, 0);
pSaveBufMgrConfig->mYuvFrameCount = GetConfParaInt(&stConfParser, SAMPLE_VirVi_YuvFrameCount, 0);
ptr = (char *)GetConfParaString(&stConfParser, SAMPLE_VirVi_YuvFilePath, NULL);
if (ptr)
strcpy(pSaveBufMgrConfig->mYuvFile, ptr);
pSaveBufMgrConfig->mRawStoreCount = GetConfParaInt(&stConfParser, SAMPLE_VirVi_RawStoreCount, 0);
pSaveBufMgrConfig->mRawStoreInterval = GetConfParaInt(&stConfParser, SAMPLE_VirVi_RawStoreInterval, 0);
ptr = (char *)GetConfParaString(&stConfParser, SAMPLE_VirVi_StoreDir, NULL);
if (ptr)
strcpy(pSaveBufMgrConfig->mStoreDirectory, ptr);
pSaveBufMgrConfig->mSavePicBufferLen = GetConfParaInt(&stConfParser, SAMPLE_VirVi_SavePicBufferLen, 0);
pSaveBufMgrConfig->mSavePicBufferNum = GetConfParaInt(&stConfParser, SAMPLE_VirVi_SavePicBufferNum, 0);
pContext->mTestDuration = GetConfParaInt(&stConfParser, SAMPLE_VirVi_Test_Duration, 0);
for(int i = 0; i < MAX_CAPTURE_NUM; i++)
{
pConfig = &pContext->mCaps[i].mConfig;
alogd("capture[%d] dev num[%d], capture size[%dx%d] format[%d] framerate[%d] colorspace[%d] drop frm[%d]", \
i, pConfig->DevNum, pConfig->PicWidth, pConfig->PicHeight, pConfig->PicFormat, \
pConfig->FrameRate, pConfig->mColorSpace, pConfig->mViDropFrmCnt);
}
alogd("save pic dev[%d], yuv count[%d] file[%s], raw count[%d] interval[%d] save dir[%s], buf len[%d] num[%d]", \
pSaveBufMgrConfig->mSavePicDev, pSaveBufMgrConfig->mYuvFrameCount, pSaveBufMgrConfig->mYuvFile, \
pSaveBufMgrConfig->mRawStoreCount, pSaveBufMgrConfig->mRawStoreInterval, pSaveBufMgrConfig->mStoreDirectory, \
pSaveBufMgrConfig->mSavePicBufferLen, pSaveBufMgrConfig->mSavePicBufferNum);
alogd("test duration[%d]", pContext->mTestDuration);
destroyConfParser(&stConfParser);
}
return SUCCESS;
}
static int saveRawData(SampleVirviSaveBufMgr *pSaveBufMgr, SampleVirviSaveBufNode *pNode)
{
SampleVirviSaveBufMgrConfig *pConfig = &pSaveBufMgr->mConfig;
//make file name, e.g., /mnt/extsd/pic[0].NV21M
char strPixFmt[16] = {0};
char fileType[16] = {0};
strcpy(fileType, "yuv");
switch(pNode->mFrmFmt)
{
case MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420:
{
strcpy(strPixFmt,"nv21");
break;
}
case MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420:
{
strcpy(strPixFmt,"nv12");
break;
}
case MM_PIXEL_FORMAT_YVU_PLANAR_420:
{
strcpy(strPixFmt,"yv12");
break;
}
case MM_PIXEL_FORMAT_YUV_PLANAR_420:
{
strcpy(strPixFmt,"yu12");
break;
}
case MM_PIXEL_FORMAT_YUV_AW_AFBC:
{
strcpy(strPixFmt, "afbc");
break;
}
case MM_PIXEL_FORMAT_YUV_AW_LBC_1_0X:
{
strcpy(strPixFmt, "lbc1_0x");
break;
}
case MM_PIXEL_FORMAT_YUV_AW_LBC_1_5X:
{
strcpy(strPixFmt, "lbc1_5x");
break;
}
case MM_PIXEL_FORMAT_YUV_AW_LBC_2_0X:
{
strcpy(strPixFmt, "lbc2_0x");
break;
}
case MM_PIXEL_FORMAT_YUV_AW_LBC_2_5X:
{
strcpy(strPixFmt, "lbc2_5x");
break;
}
case MM_PIXEL_FORMAT_RAW_SRGGB10:
{
strcpy(strPixFmt, "srggb10");
memset(fileType, 0, sizeof(fileType));
strcpy(fileType, "raw");
break;
}
default:
{
strcpy(strPixFmt,"unknown");
memset(fileType, 0, sizeof(fileType));
strcpy(fileType, "bin");
break;
}
}
char strFilePath[MAX_FILE_PATH_SIZE];
snprintf(strFilePath, MAX_FILE_PATH_SIZE, "%s/%dx%d_%s_vipp%d_%d.%s", \
pConfig->mStoreDirectory, pNode->mFrmSize.Width, pNode->mFrmSize.Height, strPixFmt, \
pConfig->mSavePicDev, pNode->mFrmCnt, fileType);
int nLen;
FILE *fpPic = fopen(strFilePath, "wb");
if(fpPic != NULL)
{
nLen = fwrite(pNode->mpDataVirAddr, 1, pNode->mFrmLen, fpPic);
if(nLen != pNode->mFrmLen)
{
aloge("fatal error! fwrite fail, write len[%d], frm len[%d], virAddr[%p]", \
nLen, pNode->mFrmLen, pNode->mpDataVirAddr);
}
alogd("virAddr[%p], length=[%d]", pNode->mpDataVirAddr, pNode->mFrmLen);
fclose(fpPic);
fpPic = NULL;
alogd("store raw frame in file[%s]", strFilePath);
}
else
{
aloge("fatal error! open file[%s] fail!", strFilePath);
}
return 0;
}
static int copyVideoFrame(VIDEO_FRAME_INFO_S *pSrc, SampleVirviSaveBufNode *pNode)
{
VideoFrameBufferSizeInfo stVideoFrmSize;
getVideoFrameBufferSizeInfo(pSrc, &stVideoFrmSize);
int nFrmsize[3] = {stVideoFrmSize.mYSize, stVideoFrmSize.mUSize, stVideoFrmSize.mVSize};
void *pTmp = pNode->mpDataVirAddr;
if (pNode->mDataLen < (nFrmsize[0]+nFrmsize[1]+nFrmsize[2]))
{
aloge("fatal error! buffer len[%d] < frame len[%d]", \
pNode->mDataLen, nFrmsize[0]+nFrmsize[1]+nFrmsize[2]);
return -1;
}
pNode->mFrmSize.Width = pSrc->VFrame.mWidth;
pNode->mFrmSize.Height = pSrc->VFrame.mHeight;
pNode->mFrmFmt = pSrc->VFrame.mPixelFormat;
for (int i = 0; i < 3; i++)
{
if (pSrc->VFrame.mpVirAddr[i])
{
memcpy(pTmp, pSrc->VFrame.mpVirAddr[i], nFrmsize[i]);
pTmp += nFrmsize[i];
pNode->mFrmLen += nFrmsize[i];
}
}
return 0;
}
static void *SaveCsiFrameThrad(void *pThreadData)
{
SampleVirViContext *pContext = (SampleVirViContext *)pThreadData;
SampleVirviSaveBufMgr *pBufMgr = pContext->mpSaveBufMgr;
SampleVirviSaveBufMgrConfig *pConfig = &pBufMgr->mConfig;
int nRawStoreNum = 0;
FILE *fp = NULL;
fp = fopen(pConfig->mYuvFile, "wb");
pBufMgr->mbTrdRunningFlag = TRUE;
while (1)
{
if (pContext->mbSaveCsiTrdExitFlag)
{
break;
}
SampleVirviSaveBufNode *pEntry = \
list_first_entry_or_null(&pBufMgr->mReadyList, SampleVirviSaveBufNode, mList);
if (pEntry)
{
pthread_mutex_lock(&pBufMgr->mIdleListLock);
if (pEntry->mFrmCnt <= pConfig->mYuvFrameCount)
{
if (fp)
{
alogd("save frm[%d] len[%d] file[%s] success!", \
pEntry->mFrmCnt, pEntry->mFrmLen, pConfig->mYuvFile);
fwrite(pEntry->mpDataVirAddr, 1, pEntry->mFrmLen, fp);
}
}
if (pConfig->mRawStoreCount > 0
&& nRawStoreNum < pConfig->mRawStoreCount
&& 0 == pEntry->mFrmCnt % pConfig->mRawStoreInterval)
{
saveRawData(pBufMgr, pEntry);
nRawStoreNum++;
}
pEntry->mFrmLen = 0;
pEntry->mFrmFmt = 0;
memset(&pEntry->mFrmSize, 0, sizeof(SIZE_S));
memset(pEntry->mpDataVirAddr, 0, pEntry->mDataLen);
pthread_mutex_lock(&pBufMgr->mReadyListLock);
list_move_tail(&pEntry->mList, &pBufMgr->mIdleList);
pthread_mutex_unlock(&pBufMgr->mReadyListLock);
pthread_mutex_unlock(&pBufMgr->mIdleListLock);
}
else
{
usleep(10*1000);
}
}
if (fp)
{
fclose(fp);
fp = NULL;
}
return (void *)NULL;
}
static void *GetCSIFrameThread(void *pThreadData)
{
int ret = 0;
int frm_cnt = 0;
SampleVirviCap *pCap = (SampleVirviCap *)pThreadData;
SampleVirViConfig *pConfig = &pCap->mConfig;
SampleVirViContext *pContext = pCap->mpContext;
SampleVirviSaveBufMgr *pBufMgr = pContext->mpSaveBufMgr;
SampleVirviSaveBufMgrConfig *pBufMgrConfig = &pBufMgr->mConfig;
alogd("loop Sample_virvi, Cap threadid=0x%lx, ViDev = %d, ViCh = %d", \
pCap->thid, pCap->Dev, pCap->Chn);
pCap->mbTrdRunning = TRUE;
pCap->mRawStoreNum = 0;
while (1)
{
if (pCap->mbExitFlag)
{
break;
}
// vi get frame
if ((ret = AW_MPI_VI_GetFrame(pCap->Dev, pCap->Chn, &pCap->pstFrameInfo, pCap->s32MilliSec)) != 0)
{
// printf("VI Get Frame failed!\n");
continue ;
}
frm_cnt++;
if (frm_cnt % 60 == 0)
{
time_t now;
struct tm *timenow;
time(&now);
timenow = localtime(&now);
alogd("Cap threadid=0x%lx, ViDev=%d,VirVi=%d,mpts=%lld; local time is %s", \
pCap->thid, pCap->Dev, pCap->Chn, pCap->pstFrameInfo.VFrame.mpts, asctime(timenow));
}
if (NULL != pBufMgr)
{
if (pBufMgrConfig->mSavePicDev == pCap->Dev)
{
SampleVirviSaveBufNode *pEntry = \
list_first_entry_or_null(&pBufMgr->mIdleList, SampleVirviSaveBufNode, mList);
if (pEntry)
{
pthread_mutex_lock(&pBufMgr->mIdleListLock);
ret = copyVideoFrame(&pCap->pstFrameInfo, pEntry);
if (!ret)
{
pEntry->mpCap = (void *)pCap;
pEntry->mFrmCnt = frm_cnt;
pthread_mutex_lock(&pBufMgr->mReadyListLock);
list_move_tail(&pEntry->mList, &pBufMgr->mReadyList);
pthread_mutex_unlock(&pBufMgr->mReadyListLock);
}
pthread_mutex_unlock(&pBufMgr->mIdleListLock);
}
}
}
// vi release frame
AW_MPI_VI_ReleaseFrame(pCap->Dev, pCap->Chn, &pCap->pstFrameInfo);
}
alogd("vi dev[%d] get csi frame trd exit!", pCap->Dev);
return NULL;
}
static SampleVirviSaveBufMgr *SampleVirviInitSaveBufMgr(SampleVirViContext *pContext)
{
SampleVirviSaveBufMgr *pSaveBufMgr = NULL;
SampleVirviSaveBufMgrConfig *pConfig = NULL;
pSaveBufMgr = malloc(sizeof(SampleVirviSaveBufMgr));
if (NULL == pSaveBufMgr)
{
aloge("fatal error! save buffer mgr malloc fail!");
return NULL;
}
memset(pSaveBufMgr, 0, sizeof(SampleVirviSaveBufMgr));
pConfig = &pSaveBufMgr->mConfig;
memset(pConfig, 0, sizeof(SampleVirviSaveBufMgrConfig));
memcpy(pConfig, &pContext->mSaveBufMgrConfig, sizeof(SampleVirviSaveBufMgrConfig));
INIT_LIST_HEAD(&pSaveBufMgr->mIdleList);
INIT_LIST_HEAD(&pSaveBufMgr->mReadyList);
pthread_mutex_init(&pSaveBufMgr->mIdleListLock, NULL);
pthread_mutex_init(&pSaveBufMgr->mReadyListLock, NULL);
for (int i = 0; i < pConfig->mSavePicBufferNum; i++)
{
SampleVirviSaveBufNode *pNode = malloc(sizeof(SampleVirviSaveBufNode));
if (NULL == pNode)
{
aloge("fatal error! malloc save buf node fail!");
return NULL;
}
memset(pNode, 0, sizeof(SampleVirviSaveBufNode));
pNode->mId = i;
pNode->mDataLen = pConfig->mSavePicBufferLen;
AW_MPI_SYS_MmzAlloc_Cached(&pNode->mDataPhyAddr, &pNode->mpDataVirAddr, pNode->mDataLen);
if ((0 == pNode->mDataPhyAddr) || (NULL == pNode->mpDataVirAddr))
{
aloge("fatal error! alloc buf[%d] fail!", i);
return NULL;
}
memset(pNode->mpDataVirAddr, 0, pNode->mDataLen);
alogd("node[%d] alloc data len[%d] phy addr[%d] vir addr[%p]", \
i, pNode->mDataLen, pNode->mDataPhyAddr, pNode->mpDataVirAddr);
pthread_mutex_lock(&pSaveBufMgr->mIdleListLock);
list_add_tail(&pNode->mList, &pSaveBufMgr->mIdleList);
pthread_mutex_unlock(&pSaveBufMgr->mIdleListLock);
}
return pSaveBufMgr;
}
static int SampleVirviDeinitSaveBufMgr(SampleVirviSaveBufMgr *pSaveBufMgr)
{
if (NULL == pSaveBufMgr)
{
alogw("why save buf mgr is null");
return -1;
}
SampleVirviSaveBufNode *pEntry = NULL, *pTmp = NULL;
pthread_mutex_lock(&pSaveBufMgr->mReadyListLock);
if (list_empty(&pSaveBufMgr->mReadyList))
{
list_for_each_entry_safe(pEntry, pTmp, &pSaveBufMgr->mReadyList, mList)
{
list_move_tail(&pEntry->mList, &pSaveBufMgr->mIdleList);
}
}
pthread_mutex_unlock(&pSaveBufMgr->mReadyListLock);
pthread_mutex_lock(&pSaveBufMgr->mIdleListLock);
list_for_each_entry_safe(pEntry, pTmp, &pSaveBufMgr->mIdleList, mList)
{
if (NULL == pEntry)
continue;
if (0 != pEntry->mDataPhyAddr && NULL != pEntry->mpDataVirAddr)
{
alogd("node[%d] alloc data len[%d] phy addr[%d] vir addr[%p]", \
pEntry->mId, pEntry->mDataLen, pEntry->mDataPhyAddr, pEntry->mpDataVirAddr);
AW_MPI_SYS_MmzFree(pEntry->mDataPhyAddr, pEntry->mpDataVirAddr);
pEntry->mDataPhyAddr = 0;
pEntry->mpDataVirAddr = NULL;
}
list_del(&pEntry->mList);
free(pEntry);
pEntry = NULL;
}
pthread_mutex_unlock(&pSaveBufMgr->mIdleListLock);
pthread_mutex_destroy(&pSaveBufMgr->mIdleListLock);
pthread_mutex_destroy(&pSaveBufMgr->mReadyListLock);
return 0;
}
static void SampleVirviInitCaps(SampleVirViContext *pContext)
{
SampleVirviCap *pCap = NULL;
SampleVirViConfig *pConfig = NULL;
for (int i = 0; i < MAX_CAPTURE_NUM; i++)
{
pCap = &pContext->mCaps[i];
pConfig = &pCap->mConfig;
pCap->Dev = MM_INVALID_DEV;
pCap->mIspDev = MM_INVALID_DEV;
pCap->Chn = MM_INVALID_CHN;
if ((pConfig->DevNum < 0) || \
(0 == pConfig->PicWidth) || (0 == pConfig->PicHeight))
{
pCap->mbCapValid = FALSE;
}
else
{
pCap->mbCapValid = TRUE;
pCap->mpContext = (void *)pContext;
}
}
}
static void SampleVirviConfigViAttr(VI_ATTR_S *pViAttr, SampleVirViConfig *pConfig)
{
pViAttr->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
pViAttr->memtype = V4L2_MEMORY_MMAP;
pViAttr->format.pixelformat = map_PIXEL_FORMAT_E_to_V4L2_PIX_FMT(pConfig->PicFormat);
pViAttr->format.field = V4L2_FIELD_NONE;
pViAttr->format.colorspace = pConfig->mColorSpace;
pViAttr->format.width = pConfig->PicWidth;
pViAttr->format.height = pConfig->PicHeight;
pViAttr->nbufs = 3;
pViAttr->nplanes = 2;
pViAttr->fps = pConfig->FrameRate;
pViAttr->use_current_win = 0;
pViAttr->wdr_mode = pConfig->mEnableWDRMode;
pViAttr->capturemode = V4L2_MODE_VIDEO; /* V4L2_MODE_VIDEO; V4L2_MODE_IMAGE; V4L2_MODE_PREVIEW */
pViAttr->drop_frame_num = pConfig->mViDropFrmCnt; // drop 2 second video data, default=0
}
static int SampleVirviPrepare(SampleVirviCap *pCap)
{
ERRORTYPE eRet = SUCCESS;
SampleVirViConfig *pConfig = &pCap->mConfig;
if (!pCap->mbCapValid)
{
return 0;
}
VI_ATTR_S stVIAttr;
memset(&stVIAttr, 0, sizeof(VI_ATTR_S));
SampleVirviConfigViAttr(&stVIAttr, &pCap->mConfig);
pCap->Dev = pConfig->DevNum;
eRet = AW_MPI_VI_CreateVipp(pCap->Dev);
if (eRet)
{
pCap->Dev = MM_INVALID_DEV;
aloge("fatal error! vi dev[%d] create fail!", pCap->Dev);
return -1;
}
eRet = AW_MPI_VI_SetVippAttr(pCap->Dev, &stVIAttr);
if (eRet)
{
aloge("fatal error! vi dev[%d] set vipp attr fail!", pCap->Dev);
}
pCap->mIspDev = pConfig->mIspDevNum;
if (pCap->mIspDev >= 0)
{
eRet = AW_MPI_ISP_Run(pCap->mIspDev);
if (eRet)
{
pCap->mIspDev = MM_INVALID_DEV;
aloge("fatal error! isp[%d] start fail!", pCap->mIspDev);
}
}
eRet = AW_MPI_VI_EnableVipp(pCap->Dev);
if (eRet)
{
aloge("fatal error! vi dev[%d] enable fail!", pCap->Dev);
}
pCap->Chn = 0;
eRet = AW_MPI_VI_CreateVirChn(pCap->Dev, pCap->Chn, NULL);
if (eRet)
{
pCap->Chn = MM_INVALID_DEV;
aloge("fatal error! vi dev[%d] create vi chn[0] fail!", pCap->Dev);
return -1;
}
alogd("create vi dev[%d] vi chn[%d] success!", pCap->Dev, pCap->Chn);
return 0;
}
static int SampleVirviStart(SampleVirviCap *pCap)
{
ERRORTYPE eRet = SUCCESS;
if (pCap->Dev < 0 || pCap->Chn < 0)
{
return 0;
}
eRet = AW_MPI_VI_EnableVirChn(pCap->Dev, pCap->Chn);
if (eRet)
{
aloge("fatal error! vi dev[%d] enable virvi chn[%d] fail!", pCap->Dev, pCap->Chn);
return -1;
}
pthread_create(&pCap->thid, NULL, GetCSIFrameThread, (void *)pCap);
return 0;
}
static int SampleVirviStop(SampleVirviCap *pCap)
{
if (pCap->mbTrdRunning)
{
pCap->mbExitFlag = TRUE;
pthread_join(pCap->thid, NULL);
}
if (pCap->Chn >= 0)
{
AW_MPI_VI_DisableVirChn(pCap->Dev, pCap->Chn);
AW_MPI_VI_DestroyVirChn(pCap->Dev, pCap->Chn);
}
if (pCap->Dev >= 0)
{
AW_MPI_VI_DisableVipp(pCap->Dev);
if (pCap->mIspDev >= 0)
AW_MPI_ISP_Stop(pCap->mIspDev);
AW_MPI_VI_DestroyVipp(pCap->Dev);
}
return 0;
}
int main(int argc, char *argv[])
{
int result = 0;
int vipp_dev, virvi_chn;
int count = 0;
pthread_t saveFrmTrd;
printf("Sample virvi buile time = %s, %s.\r\n", __DATE__, __TIME__);
SampleVirViContext *pContext = (SampleVirViContext*)malloc(sizeof(SampleVirViContext));
memset(pContext, 0, sizeof(SampleVirViContext));
gpSampleVirViContext = pContext;
SampleVirviCap *pCap = NULL;
cdx_sem_init(&pContext->mSemExit, 0);
if (signal(SIGINT, handle_exit) == SIG_ERR)
{
aloge("fatal error! can't catch SIGSEGV");
}
char *pConfigFilePath;
if (argc > 1)
{
/* parse command line param,read sample_virvi.conf */
if(ParseCmdLine(argc, argv, &pContext->mCmdLinePara) != 0)
{
aloge("fatal error! command line param is wrong, exit!");
result = -1;
goto _exit;
}
if(strlen(pContext->mCmdLinePara.mConfigFilePath) > 0)
{
pConfigFilePath = pContext->mCmdLinePara.mConfigFilePath;
}
else
{
pConfigFilePath = DEFAULT_SAMPLE_VIRVI_CONF_PATH;
}
}
else
{
pConfigFilePath = NULL;
}
/* parse config file. */
if(loadConfigPara(pContext, pConfigFilePath) != SUCCESS)
{
aloge("fatal error! no config file or parse conf file fail");
result = -1;
goto _exit;
}
SampleVirviInitCaps(pContext);
MPP_SYS_CONF_S stConf;
memset(&stConf, 0, sizeof(MPP_SYS_CONF_S));
AW_MPI_SYS_SetConf(&stConf);
result = AW_MPI_SYS_Init();
if (SUCCESS != result)
{
goto _exit;
}
if (pContext->mSaveBufMgrConfig.mSavePicDev >= 0 && \
pContext->mSaveBufMgrConfig.mSavePicBufferLen >= 0 && \
pContext->mSaveBufMgrConfig.mSavePicBufferNum >= 0)
{
pContext->mpSaveBufMgr = SampleVirviInitSaveBufMgr(pContext);
if (NULL == pContext->mpSaveBufMgr)
{
result = -1;
aloge("fatal error! init save csi frame mgr fail!");
goto _deinit_buf_mgr;
}
pthread_create(&saveFrmTrd, NULL, SaveCsiFrameThrad, (void *)pContext);
}
for (int i = 0; i < MAX_CAPTURE_NUM; i++)
{
pCap = &pContext->mCaps[i];
result = SampleVirviPrepare(pCap);
if (result)
{
result = -1;
aloge("fatal error! capture[%d] prepare fail!", i);
goto _deinit_buf_mgr;
}
}
for (int i = 0; i < MAX_CAPTURE_NUM; i++)
{
pCap = &pContext->mCaps[i];
result = SampleVirviStart(pCap);
if (result)
{
aloge("fatal error! capture[%d] start fail!", i);
goto _stop;
}
}
if (pContext->mTestDuration > 0)
{
cdx_sem_down_timedwait(&pContext->mSemExit, pContext->mTestDuration*1000);
}
else
{
cdx_sem_wait(&pContext->mSemExit);
}
_stop:
for (int i = 0; i < MAX_CAPTURE_NUM; i++)
{
pCap = &pContext->mCaps[i];
result = SampleVirviStop(pCap);
if (result)
{
aloge("fatal error! capture[%d] stop fail!", i);
}
}
int disp_fd;
_deinit_buf_mgr:
if (pContext->mpSaveBufMgr)
{
pContext->mbSaveCsiTrdExitFlag = TRUE;
if (pContext->mpSaveBufMgr->mbTrdRunningFlag)
pthread_join(saveFrmTrd, NULL);
SampleVirviDeinitSaveBufMgr(pContext->mpSaveBufMgr);
}
AW_MPI_SYS_Exit();
cdx_sem_deinit(&pContext->mSemExit);
free(pContext);
_exit:
disp_fd = open("/dev/fb0", O_RDWR);
if (disp_fd < 0)
{
alogd("[%s] open fb0 fail!\n", LOG_TAG);
}
printf("%s", ((0 == result) ? "PASS" : "FAIL"));
return result;
}