2983 lines
131 KiB
C
Executable File
2983 lines
131 KiB
C
Executable File
/******************************************************************************
|
|
Copyright (C), 2018-2020, Allwinner Tech. Co., Ltd.
|
|
******************************************************************************
|
|
File Name : VideoEIS_Component.c
|
|
Version : Initial Draft
|
|
Author : Allwinner PDC-PD5 Team
|
|
Created : 2018/04/20
|
|
Last Modified :
|
|
Description : EIS mpp component implement
|
|
Function List :
|
|
History :
|
|
******************************************************************************/
|
|
|
|
#define LOG_TAG "VideoEIS_Component"
|
|
#include <utils/plat_log.h>
|
|
|
|
//ref platform headers
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/prctl.h>
|
|
#include <pthread.h>
|
|
#include <sched.h>
|
|
#include <sys/syscall.h>
|
|
|
|
#include "plat_defines.h"
|
|
#include "plat_errno.h"
|
|
#include "plat_math.h"
|
|
#include "plat_type.h"
|
|
#include "cdx_list.h"
|
|
|
|
#include "SystemBase.h"
|
|
#include <VIDEO_FRAME_INFO_S.h>
|
|
#include "mm_comm_eis.h"
|
|
#include "mm_comm_video.h"
|
|
#include "mm_comm_vi.h"
|
|
#include "mm_common.h"
|
|
|
|
#include "ComponentCommon.h"
|
|
#include "media_common.h"
|
|
#include "mm_component.h"
|
|
#include "tmessage.h"
|
|
#include "tsemaphore.h"
|
|
#include "vencoder.h"
|
|
#include "ion_memmanager.h"
|
|
|
|
#include "VideoEIS_Component.h"
|
|
#include "video_buffer_manager.h"
|
|
#include "utils/ring_buffer.h"
|
|
#include "utils/iio_utils.h"
|
|
#include "utils/generic_buffer.h"
|
|
#include "algo/include/EIS_lib.h"
|
|
|
|
typedef struct VideoEisPrivAttr {
|
|
float fGyroAxScaleFactor;
|
|
float fGyroAyScaleFactor;
|
|
float fGyroAzScaleFactor;
|
|
float fGyroVxScaleFactor;
|
|
float fGyroVyScaleFactor;
|
|
float fGyroVzScaleFactor;
|
|
} VIDEO_EIS_PRIVATTR;
|
|
|
|
typedef struct VideoEisDataType {
|
|
COMP_STATETYPE state;
|
|
pthread_mutex_t mStateLock;
|
|
COMP_CALLBACKTYPE* pCallbacks;
|
|
void* pAppData;
|
|
COMP_HANDLETYPE hSelf;
|
|
|
|
COMP_PORT_PARAM_TYPE sPortParam;
|
|
COMP_PARAM_PORTDEFINITIONTYPE sPortDef[EIS_CHN_MAX_PORTS];
|
|
COMP_INTERNAL_TUNNELINFOTYPE sPortTunnelInfo[EIS_CHN_MAX_PORTS];
|
|
COMP_PARAM_BUFFERSUPPLIERTYPE sPortBufSupplier[EIS_CHN_MAX_PORTS];
|
|
/* TRUE: tunnel mode; FALSE: non-tunnel mode. */
|
|
bool bInputPortTunnelFlag;
|
|
bool bOutputPortTunnelFlag;
|
|
|
|
MPP_CHN_S mMppChnInfo;
|
|
pthread_t mEISTrd;
|
|
message_queue_t cmd_queue;
|
|
|
|
/* Gyro informations */
|
|
pthread_t mGyroTrd;
|
|
bool bGyroRunFlag;
|
|
bool bHasGyroDev;
|
|
struct gyro_device_attr mGyroAttr;
|
|
struct ring_buffer* GryoRingBufHd;
|
|
unsigned int iGVSyncPktId;
|
|
struct gyro_instance *pGyroIns;
|
|
|
|
/* Video buffer informations */
|
|
bool bWaitingInputFrmFlag;
|
|
VideoBufferManager *pInputBufMgr;
|
|
pthread_mutex_t mInputFrmLock;
|
|
|
|
bool bWaitingOutFrmFlag;
|
|
cdx_sem_t mSemWaitOutFrame;
|
|
|
|
pthread_mutex_t mOutFrmListLock;
|
|
struct list_head mOutIdleList;
|
|
struct list_head mOutValidList;
|
|
struct list_head mOutUsedList;
|
|
int iOutFrmCnt;
|
|
int iOutFrmIdleCnt;
|
|
|
|
/* Begin from the beginning of first line exposure,
|
|
* end to the beginning of last line exposure. */
|
|
int iVideoLineTime; /* Unit: ms */
|
|
EISE_FrameData* pstEISPkt;
|
|
unsigned long long iEISPktIdx;
|
|
unsigned long long mEisPktMap; // We use map to manage EIS packets
|
|
EISE_FrameData* pLastUsedEISPkt;
|
|
uint64_t dLastInputFrmPts;
|
|
|
|
EIS_ATTR_S mEISAttr;
|
|
VIDEO_EIS_PRIVATTR mEisPrivAttr;
|
|
/* Hardware EIS attributions */
|
|
int iEisHwFreq;
|
|
EISE_HANDLE mEisHd;
|
|
EISE_CFG_PARA mEisCfg;
|
|
pthread_mutex_t mEISAttrLock;
|
|
uint64_t dEisGetInputFrmCnt;
|
|
|
|
cdx_sem_t mAllFrameRelSem;
|
|
volatile int mWaitAllFrameReleaseFlag;
|
|
bool bEnableFlag;
|
|
pthread_mutex_t mEISLock;
|
|
|
|
bool bByPassMode;
|
|
char *pBPDataSavePath;
|
|
FILE *pVideoPtsFd;
|
|
FILE *pGyroPtsDataFd;
|
|
FILE *pVideoDataFd;
|
|
int iCacheBufferNum;
|
|
bool bStoreFrame;
|
|
int mStoreFrameCount;
|
|
char mDbgStoreFrameFilePath[EIS_MAXPATHSIZE];
|
|
} VIDEOEISDATATYPE;
|
|
|
|
#define LOCK_DEBUG
|
|
//#define GYRO_DATA_SAVE_DEBUG
|
|
//#define PROC_TIME_TEST
|
|
|
|
#define TIME_INIT_START_END(x) struct timeval start_##x; \
|
|
struct timeval end_##x; \
|
|
float DiffTime_##x;
|
|
#define TIME_GET_START(x) (gettimeofday(&start_##x, NULL))
|
|
#define TIME_GET_END(x) (gettimeofday(&end_##x, NULL)); \
|
|
(DiffTime_##x = \
|
|
(((end_##x.tv_sec + end_##x.tv_usec * 1e-6) - \
|
|
(start_##x.tv_sec + start_##x.tv_usec * 1e-6)) * 1000))
|
|
#define TIME_PRINT_DIFF(x) (DiffTime_##x)
|
|
|
|
static void *EIS_CompGyroThread(void *pThreadData);
|
|
static void *EIS_CompStabThread(void *pThreadData);
|
|
|
|
ERRORTYPE DoVideoEisGetTunnelInfo(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT COMP_INTERNAL_TUNNELINFOTYPE *pTunnelInfo)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
ERRORTYPE eError = SUCCESS;
|
|
int i;
|
|
for(i = 0; i < EIS_CHN_MAX_PORTS; i++) {
|
|
if(pVideoEISData->sPortBufSupplier[i].nPortIndex == pTunnelInfo->nPortIndex) {
|
|
memcpy(pTunnelInfo, &pVideoEISData->sPortTunnelInfo[i], sizeof(COMP_INTERNAL_TUNNELINFOTYPE));
|
|
break;
|
|
}
|
|
}
|
|
if(i == EIS_CHN_MAX_PORTS) {
|
|
aloge("No such port index[%d] in EIS[%d].", pTunnelInfo->nPortIndex, pVideoEISData->mMppChnInfo.mChnId);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
static void DoVideoEisStoreProcessedFrm(VIDEOEISDATATYPE* pVideoEISData, VIDEO_FRAME_INFO_S* SFrame)
|
|
{
|
|
char strPixFmt[16];
|
|
if(MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420==SFrame->VFrame.mPixelFormat || MM_PIXEL_FORMAT_AW_NV21S==SFrame->VFrame.mPixelFormat)
|
|
strcpy(strPixFmt, "nv21");
|
|
else if(MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420 == SFrame->VFrame.mPixelFormat)
|
|
strcpy(strPixFmt, "nv12");
|
|
else
|
|
strcpy(strPixFmt, "unknown");
|
|
|
|
int nPos = strlen(pVideoEISData->mDbgStoreFrameFilePath);
|
|
snprintf(pVideoEISData->mDbgStoreFrameFilePath+nPos, EIS_MAXPATHSIZE-nPos,
|
|
"/EisChn[%d]Pic[%d].%s",
|
|
pVideoEISData->mMppChnInfo.mChnId, pVideoEISData->mStoreFrameCount++, strPixFmt);
|
|
FILE *dbgFp = fopen(pVideoEISData->mDbgStoreFrameFilePath, "wb");
|
|
VideoFrameBufferSizeInfo FrameSizeInfo;
|
|
getVideoFrameBufferSizeInfo(SFrame, &FrameSizeInfo);
|
|
int yuvSize[3] = {FrameSizeInfo.mYSize, FrameSizeInfo.mUSize, FrameSizeInfo.mVSize};
|
|
for(int i = 0; i < 3; i++) {
|
|
if(SFrame->VFrame.mpVirAddr[i] != NULL) {
|
|
fwrite(SFrame->VFrame.mpVirAddr[i], 1, yuvSize[i], dbgFp);
|
|
alogd("virAddr[%d]=[%p], length=[%d]", i, SFrame->VFrame.mpVirAddr[i], yuvSize[i]);
|
|
}
|
|
}
|
|
fclose(dbgFp);
|
|
alogd("Store EIS frame in file[%s]", pVideoEISData->mDbgStoreFrameFilePath);
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisGetData(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_OUT EIS_PARAMS_S *pstParams, PARAM_IN int nMilliSec)
|
|
{
|
|
ERRORTYPE eError = SUCCESS;
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
if (COMP_StateIdle != pVideoEISData->state && COMP_StateExecuting != pVideoEISData->state) {
|
|
alogw("call getStream in wrong state[0x%x]", pVideoEISData->state);
|
|
return ERR_VI_NOT_PERM;
|
|
}
|
|
int ret;
|
|
|
|
/* not support get data in Tunnel mode for app */
|
|
if (TRUE == pVideoEISData->bOutputPortTunnelFlag) {
|
|
aloge("You are in output bind mode, do not get data in yourself.");
|
|
return ERR_VI_NOT_PERM;
|
|
}
|
|
|
|
VIDEO_FRAME_INFO_S *pstFrameInfo = pstParams->pstFrameInfo;
|
|
VideoFrameListInfo *pVFrmListTmp = NULL;
|
|
_TryToGetFrame:
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
if (!list_empty(&pVideoEISData->mOutValidList)) {
|
|
pVFrmListTmp = list_first_entry(&pVideoEISData->mOutValidList, VideoFrameListInfo, mList);
|
|
memcpy(pstFrameInfo, &pVFrmListTmp->mFrame, sizeof(VIDEO_FRAME_INFO_S));
|
|
pstFrameInfo->VFrame.mOffsetTop = 0;
|
|
pstFrameInfo->VFrame.mOffsetBottom = pstFrameInfo->VFrame.mHeight;
|
|
pstFrameInfo->VFrame.mOffsetLeft = 0;
|
|
pstFrameInfo->VFrame.mOffsetRight = pstFrameInfo->VFrame.mWidth;
|
|
|
|
if(pVideoEISData->bStoreFrame) {
|
|
DoVideoEisStoreProcessedFrm(pVideoEISData, pstFrameInfo);
|
|
pVideoEISData->bStoreFrame = FALSE;
|
|
}
|
|
eError = SUCCESS;
|
|
list_move_tail(&pVFrmListTmp->mList, &pVideoEISData->mOutUsedList);
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
} else {
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
if(0 == nMilliSec) {
|
|
eError = ERR_EIS_BUF_EMPTY;
|
|
} else if(nMilliSec < 0) {
|
|
pVideoEISData->bWaitingOutFrmFlag = TRUE;
|
|
cdx_sem_down(&pVideoEISData->mSemWaitOutFrame);
|
|
pVideoEISData->bWaitingOutFrmFlag = FALSE;
|
|
goto _TryToGetFrame;
|
|
} else {
|
|
pVideoEISData->bWaitingOutFrmFlag = TRUE;
|
|
ret = cdx_sem_down_timedwait(&pVideoEISData->mSemWaitOutFrame, nMilliSec);
|
|
if(0 == ret) {
|
|
pVideoEISData->bWaitingOutFrmFlag = FALSE;
|
|
goto _TryToGetFrame;
|
|
} else {
|
|
aloge("Fatal error! EIS[%d] pthread cond wait timeout ret[%d]", pVideoEISData->mMppChnInfo.mChnId, ret);
|
|
eError = ERR_EIS_BUF_EMPTY;
|
|
pVideoEISData->bWaitingOutFrmFlag = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisReleaseData(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN EIS_PARAMS_S *pstParams)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
if (COMP_StateIdle != pVideoEISData->state && COMP_StateExecuting != pVideoEISData->state) {
|
|
alogw("Call getStream in wrong state[0x%x]", pVideoEISData->state);
|
|
return ERR_EIS_INVALIDSTATE;
|
|
}
|
|
if (TRUE == pVideoEISData->bOutputPortTunnelFlag) { /* Tunnel mode */
|
|
aloge("You are in output bind mode, do not get data in yourself.");
|
|
return ERR_EIS_NOT_PERM;
|
|
}
|
|
|
|
int iEisChn = pstParams->mChn;
|
|
bool bFindFlag = 0;
|
|
VIDEO_FRAME_INFO_S *pstFrameInfo = pstParams->pstFrameInfo;
|
|
VideoFrameListInfo *pVFrmList;
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
list_for_each_entry(pVFrmList, &pVideoEISData->mOutUsedList, mList)
|
|
{
|
|
if (pVFrmList->mFrame.mId == pstFrameInfo->mId ||
|
|
pVFrmList->mFrame.VFrame.mpVirAddr[0] == pstFrameInfo->VFrame.mpVirAddr[0]) {
|
|
bFindFlag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bFindFlag) {
|
|
list_move_tail(&pVFrmList->mList, &pVideoEISData->mOutIdleList);
|
|
pVideoEISData->iOutFrmIdleCnt++;
|
|
} else {
|
|
aloge("No such video frame Id[%d] is using, please check it.", pstFrameInfo->mId);
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
return ERR_EIS_INVALID_PARA;
|
|
}
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisStoreFrameOpr(PARAM_IN COMP_HANDLETYPE hComponent, const char* pDirPath)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
if (!pVideoEISData->bOutputPortTunnelFlag) {
|
|
alogw("in non-tunnel mode, you should store frame by your self, we don't do it\n");
|
|
return ERR_EIS_NOT_SUPPORT;
|
|
}
|
|
|
|
message_t msg;
|
|
InitMessage(&msg);
|
|
msg.command = EisComp_StoreFrame;
|
|
msg.mpData = (void*)pDirPath;
|
|
msg.mDataSize = strlen(pDirPath)+1;
|
|
putMessageWithData(&pVideoEISData->cmd_queue, &msg);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
ERRORTYPE VideoEISSendCommand(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_COMMANDTYPE Cmd,
|
|
PARAM_IN unsigned int nParam1, PARAM_IN void *pCmdData)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
CompInternalMsgType eCmd;
|
|
ERRORTYPE eError = SUCCESS;
|
|
message_t msg;
|
|
|
|
alogv("VideoEISSendCommand: %d", Cmd);
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
if (!pVideoEISData) {
|
|
eError = ERR_EIS_SYS_NOTREADY;
|
|
goto ENotReady;
|
|
}
|
|
|
|
if (pVideoEISData->state == COMP_StateInvalid) {
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto ENotReady;
|
|
}
|
|
switch (Cmd) {
|
|
case COMP_CommandStateSet:
|
|
eCmd = SetState;
|
|
break;
|
|
|
|
case COMP_CommandFlush:
|
|
eCmd = Flush;
|
|
break;
|
|
|
|
default:
|
|
alogw("impossible comp_command[0x%x]", Cmd);
|
|
eCmd = -1;
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
goto ENotSupport;
|
|
break;
|
|
}
|
|
|
|
msg.command = eCmd;
|
|
msg.para0 = nParam1;
|
|
put_message(&pVideoEISData->cmd_queue, &msg);
|
|
|
|
ENotSupport:
|
|
ENotReady:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE VideoEISGetState(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_OUT COMP_STATETYPE *pState)
|
|
{
|
|
ERRORTYPE eError = SUCCESS;
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
*pState = pVideoEISData->state;
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE VideoEISSetCallbacks(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_CALLBACKTYPE *pCallbacks,
|
|
PARAM_IN void *pAppData)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
if (!pVideoEISData || !pCallbacks || !pAppData) {
|
|
eError = ERR_VI_INVALID_PARA;
|
|
goto COMP_CONF_CMD_FAIL;
|
|
}
|
|
|
|
pVideoEISData->pCallbacks = pCallbacks;
|
|
pVideoEISData->pAppData = pAppData;
|
|
|
|
COMP_CONF_CMD_FAIL:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisChnConfigOpr(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_INOUT EIS_ATTR_S *pEisAttr,
|
|
PARAM_IN EIS_CONF_OPR_E eConfOpr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
switch (eConfOpr) {
|
|
case EIS_CHN_CONF_SET: {
|
|
if (pEisAttr) {
|
|
memcpy(&pVideoEISData->mEISAttr, pEisAttr, sizeof(EIS_ATTR_S));
|
|
pVideoEISData->mGyroAttr.sample_freq = pEisAttr->iGyroFreq;
|
|
pVideoEISData->mGyroAttr.axi_num = pEisAttr->iGyroAxiNum;
|
|
}
|
|
} break;
|
|
case EIS_CHN_CONF_GET: {
|
|
if (pEisAttr)
|
|
memcpy(pEisAttr, &pVideoEISData->mEISAttr, sizeof(EIS_ATTR_S));
|
|
else {
|
|
aloge("You input a NULL pointer to store EIS attribution, fix it.");
|
|
eError = ERR_EIS_INVALID_NULL_PTR;
|
|
}
|
|
} break;
|
|
default: {
|
|
aloge("Wrong config operation[%d].", eConfOpr);
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoSetEisChnAlgoModeOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT EIS_ALGO_MODE *pEisAttr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
if (NULL == pEisAttr) {
|
|
aloge("You input a NULL pointer to store EIS attribution, fix it.");
|
|
eError = ERR_EIS_INVALID_NULL_PTR;
|
|
goto ENullPtr;
|
|
}
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mStateLock);
|
|
if (pVideoEISData->state != COMP_StateIdle && pVideoEISData->state != COMP_StateLoaded) {
|
|
aloge("Send frame when EIS component state[0x%x].", pVideoEISData->state);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EState;
|
|
}
|
|
|
|
EState:
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
|
|
ENullPtr:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoSetEisChnVFmtOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT EIS_VIDEO_FMT_ATTR_S *pEisAttr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
if (NULL == pEisAttr) {
|
|
aloge("You input a NULL pointer to store EIS attribution, fix it.");
|
|
eError = ERR_EIS_INVALID_NULL_PTR;
|
|
goto ENullPtr;
|
|
}
|
|
pthread_mutex_lock(&pVideoEISData->mStateLock);
|
|
if (pVideoEISData->state != COMP_StateIdle && pVideoEISData->state != COMP_StateLoaded) {
|
|
aloge("Send frame when EIS component state[0x%x].", pVideoEISData->state);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EState;
|
|
}
|
|
|
|
pVideoEISData->mEISAttr.iVideoInWidth = pEisAttr->iVideoInWidth;
|
|
pVideoEISData->mEISAttr.iVideoInWidthStride = pEisAttr->iVideoInWidthStride;
|
|
pVideoEISData->mEISAttr.iVideoInHeight = pEisAttr->iVideoInHeight;
|
|
pVideoEISData->mEISAttr.iVideoInHeightStride = pEisAttr->iVideoInHeightStride;
|
|
pVideoEISData->mEISAttr.iVideoOutWidth = pEisAttr->iVideoOutWidth;
|
|
pVideoEISData->mEISAttr.iVideoOutHeight = pEisAttr->iVideoOutHeight;
|
|
pVideoEISData->mEISAttr.eVideoFmt = pEisAttr->eVideoFmt;
|
|
|
|
EState:
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
|
|
ENullPtr:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoSetEisChnDataProcOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT EIS_DATA_PROC_ATTR_S *pEisAttr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
if (NULL == pEisAttr) {
|
|
aloge("You input a NULL pointer to store EIS attribution, fix it.");
|
|
eError = ERR_EIS_INVALID_NULL_PTR;
|
|
goto ENullPtr;
|
|
}
|
|
pthread_mutex_lock(&pVideoEISData->mStateLock);
|
|
if (pVideoEISData->state != COMP_StateIdle && pVideoEISData->state != COMP_StateLoaded) {
|
|
aloge("Send frame when EIS component state[0x%x].", pVideoEISData->state);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EState;
|
|
}
|
|
|
|
pVideoEISData->mEISAttr.bRetInFrmFast = pEisAttr->bRetInFrmFast;
|
|
pVideoEISData->mEISAttr.bHorizFlip = pEisAttr->bHorizFlip;
|
|
pVideoEISData->mEISAttr.bVerticalFlip = pEisAttr->bVerticalFlip;
|
|
pVideoEISData->mEISAttr.iInputBufNum = pEisAttr->iInputBufNum;
|
|
pVideoEISData->mEISAttr.iOutputBufBum = pEisAttr->iOutputBufBum;
|
|
pVideoEISData->mEISAttr.iDelayTimeMs = pEisAttr->iDelayTimeMs;
|
|
pVideoEISData->mEISAttr.iEisFilterWidth = pEisAttr->iEisFilterWidth;
|
|
pVideoEISData->mEISAttr.iSyncErrTolerance = pEisAttr->iSyncErrTolerance;
|
|
|
|
EState:
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
|
|
ENullPtr:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoSetEisChnGyroOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT EIS_GYRO_DATA_ATTR_S *pEisAttr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
if (NULL == pEisAttr) {
|
|
aloge("You input a NULL pointer to store EIS attribution, fix it.");
|
|
eError = ERR_EIS_INVALID_NULL_PTR;
|
|
goto ENullPtr;
|
|
}
|
|
pthread_mutex_lock(&pVideoEISData->mStateLock);
|
|
if (pVideoEISData->state != COMP_StateIdle && pVideoEISData->state != COMP_StateLoaded) {
|
|
aloge("Send frame when EIS component state[0x%x].", pVideoEISData->state);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EState;
|
|
}
|
|
|
|
pVideoEISData->mEISAttr.iGyroFreq = pEisAttr->iGyroFreq;
|
|
pVideoEISData->mEISAttr.iGyroPoolSize = pEisAttr->iGyroPoolSize;
|
|
pVideoEISData->mEISAttr.iGyroAxiNum = pEisAttr->iGyroAxiNum;
|
|
|
|
EState:
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
|
|
ENullPtr:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoSetEisChnKmatOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT EIS_KMAT_S *pEisAttr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
if (NULL == pEisAttr) {
|
|
aloge("You input a NULL pointer to store EIS attribution, fix it.");
|
|
eError = ERR_EIS_INVALID_NULL_PTR;
|
|
goto ENullPtr;
|
|
}
|
|
pthread_mutex_lock(&pVideoEISData->mStateLock);
|
|
if (pVideoEISData->state != COMP_StateIdle && pVideoEISData->state != COMP_StateLoaded) {
|
|
aloge("Send frame when EIS component state[0x%x].", pVideoEISData->state);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EState;
|
|
}
|
|
|
|
pVideoEISData->mEISAttr.bUseKmat = 1;
|
|
pVideoEISData->mEISAttr.stEisKmat = *pEisAttr;
|
|
|
|
EState:
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
|
|
ENullPtr:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisMPPChannelInfoOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_IN MPP_CHN_S *pstInfo, PARAM_IN EIS_CONF_OPR_E eConfOpr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
switch (eConfOpr) {
|
|
case EIS_CHN_CONF_SET: {
|
|
copy_MPP_CHN_S(&pVideoEISData->mMppChnInfo, pstInfo);
|
|
} break;
|
|
case EIS_CHN_CONF_GET: {
|
|
copy_MPP_CHN_S(pstInfo, &pVideoEISData->mMppChnInfo);
|
|
} break;
|
|
default: {
|
|
aloge("Wrong config operation[%d].", eConfOpr);
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE _EisEnableGyroDeviceMulElem(VIDEOEISDATATYPE *pVideoEISData, int iEnableFlag)
|
|
{
|
|
ERRORTYPE eError = SUCCESS;
|
|
int iRet = 0;
|
|
|
|
if (iEnableFlag) {
|
|
if (!pVideoEISData->mEISAttr.bSimuOffline) {
|
|
/* Online mode, then create and open the gyro device. */
|
|
pVideoEISData->pGyroIns = create_gyro_inst();
|
|
if (NULL == pVideoEISData->pGyroIns) {
|
|
aloge("Create gyro instance failed.");
|
|
eError = ERR_EIS_NOMEM;
|
|
goto ECrtIns;
|
|
}
|
|
|
|
iRet = gyro_ins_open(pVideoEISData->pGyroIns, &pVideoEISData->mGyroAttr);
|
|
if (0 != iRet) {
|
|
aloge("FFFFFFatal error, open gyro instance failed, we will use \"zero\" datas as valid gyro datas.");
|
|
pVideoEISData->bHasGyroDev = 0;
|
|
pVideoEISData->GryoRingBufHd = ring_buffer_create(sizeof(EIS_GYRO_PACKET_S),
|
|
pVideoEISData->mEISAttr.iGyroPoolSize, RB_FL_NONE);
|
|
if (NULL == pVideoEISData->GryoRingBufHd) {
|
|
aloge("Create ring buffer for gyro buffers failed.");
|
|
eError = ERR_EIS_NOMEM;
|
|
goto EOpenIns;
|
|
}
|
|
} else {
|
|
pVideoEISData->bHasGyroDev = 1;
|
|
pVideoEISData->GryoRingBufHd = gyro_ins_get_rbhdl(pVideoEISData->pGyroIns);
|
|
}
|
|
|
|
if (pVideoEISData->mEISAttr.eEisAlgoMode == EIS_ALGO_MODE_BP)
|
|
pVideoEISData->bByPassMode = 1;
|
|
|
|
if (pVideoEISData->bByPassMode) {
|
|
pVideoEISData->bGyroRunFlag = 1;
|
|
if (pthread_create(&pVideoEISData->mGyroTrd, NULL, EIS_CompGyroThread, pVideoEISData)) {
|
|
aloge("create EIS_CompGyroThread failed!");
|
|
eError = ERR_EIS_FAILED_NOTENABLE;
|
|
pVideoEISData->bGyroRunFlag = 0;
|
|
goto ECrtThread;
|
|
}
|
|
}
|
|
} else {
|
|
/* Offline simulation mode, just create ring_buffer module. */
|
|
pVideoEISData->GryoRingBufHd = ring_buffer_create(sizeof(EIS_GYRO_PACKET_S),
|
|
pVideoEISData->mEISAttr.iGyroPoolSize, RB_FL_NONE);
|
|
if (NULL == pVideoEISData->GryoRingBufHd) {
|
|
aloge("Create ring buffer for gyro buffers failed.");
|
|
eError = ERR_EIS_NOMEM;
|
|
goto ECrtBuffer;
|
|
}
|
|
}
|
|
} else {
|
|
if (!pVideoEISData->mEISAttr.bSimuOffline) {
|
|
/* Close and wait gyro read thread exit. */
|
|
if (pVideoEISData->pGyroIns) {
|
|
if (pVideoEISData->bByPassMode) {
|
|
pVideoEISData->bGyroRunFlag = 0;
|
|
pthread_join(pVideoEISData->mGyroTrd, NULL);
|
|
pVideoEISData->mGyroTrd = 0;
|
|
}
|
|
/* If we got no gyro device, then we should destroy ring buffer by ourselves. */
|
|
if (!pVideoEISData->bHasGyroDev && pVideoEISData->GryoRingBufHd)
|
|
ring_buffer_destroy(pVideoEISData->GryoRingBufHd);
|
|
gyro_ins_close(pVideoEISData->pGyroIns);
|
|
destory_gyro_inst(pVideoEISData->pGyroIns);
|
|
} else {
|
|
aloge("You have not enable gyro device yet.");
|
|
eError = ERR_EIS_NOT_PERM;
|
|
}
|
|
} else {
|
|
/* Destroy ring buffers and close mpu devices */
|
|
ring_buffer_destroy(pVideoEISData->GryoRingBufHd);
|
|
}
|
|
pVideoEISData->GryoRingBufHd = NULL;
|
|
}
|
|
|
|
return eError;
|
|
|
|
ECrtThread:
|
|
gyro_ins_close(pVideoEISData->pGyroIns);
|
|
EOpenIns:
|
|
pVideoEISData->GryoRingBufHd = NULL;
|
|
destory_gyro_inst(pVideoEISData->pGyroIns);
|
|
ECrtIns:
|
|
ECrtBuffer:
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisChnEnableOpr(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN int* iEnableFlag,
|
|
PARAM_IN EIS_CONF_OPR_E eConfOpr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mEISLock);
|
|
switch (eConfOpr) {
|
|
case EIS_CHN_CONF_SET: {
|
|
/* Only when [old_val=0,new_val=1] and [old_val=1,new_val=0], we will do real operation invoke,
|
|
* else [old_val=0,new_val=0] and [old_val=0,new_val=0], just return. */
|
|
if (*iEnableFlag + pVideoEISData->bEnableFlag == 1) {
|
|
eError = _EisEnableGyroDeviceMulElem(pVideoEISData, *iEnableFlag);
|
|
if (eError != SUCCESS) {
|
|
aloge("Do enable or disable Gyro device failed. ret 0x%x.", eError);
|
|
goto EEnable;
|
|
}
|
|
pVideoEISData->bEnableFlag = *iEnableFlag;
|
|
} else
|
|
alogw("EIS[%d] has already been enabled or disabled.", pVideoEISData->mMppChnInfo.mChnId);
|
|
} break;
|
|
case EIS_CHN_CONF_GET: {
|
|
*iEnableFlag = pVideoEISData->bEnableFlag;
|
|
} break;
|
|
default: {
|
|
aloge("Wrong config operation[%d].", eConfOpr);
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
|
|
EEnable:
|
|
pthread_mutex_unlock(&pVideoEISData->mEISLock);
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisFreqOpr(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN int* iFreqVal,
|
|
PARAM_IN EIS_CONF_OPR_E eConfOpr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mEISLock);
|
|
switch (eConfOpr) {
|
|
case EIS_CHN_CONF_SET: {
|
|
pVideoEISData->iEisHwFreq = *iFreqVal;
|
|
} break;
|
|
case EIS_CHN_CONF_GET: {
|
|
*iFreqVal = pVideoEISData->iEisHwFreq;
|
|
} break;
|
|
default: {
|
|
aloge("Wrong config operation[%d].", eConfOpr);
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
|
|
EEnable:
|
|
pthread_mutex_unlock(&pVideoEISData->mEISLock);
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisPortDefinitionOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT COMP_PARAM_PORTDEFINITIONTYPE *pPortDef,
|
|
PARAM_IN EIS_CONF_OPR_E eConfOpr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEisData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
int i;
|
|
pVideoEisData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
for(i = 0; i < EIS_CHN_MAX_PORTS; i++) {
|
|
if (pPortDef->nPortIndex == pVideoEisData->sPortDef[i].nPortIndex)
|
|
break;
|
|
}
|
|
if (i == EIS_CHN_MAX_PORTS) {
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
} else {
|
|
switch (eConfOpr) {
|
|
case EIS_CHN_CONF_SET: {
|
|
memcpy(&pVideoEisData->sPortDef[i], pPortDef, sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
|
|
} break;
|
|
case EIS_CHN_CONF_GET: {
|
|
memcpy(pPortDef, &pVideoEisData->sPortDef[i], sizeof(COMP_PARAM_PORTDEFINITIONTYPE));
|
|
} break;
|
|
default: {
|
|
aloge("Wrong config operation[%d].", eConfOpr);
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE DoVideoEisCompBufferSupplierOpr(PARAM_IN COMP_HANDLETYPE hComponent,
|
|
PARAM_INOUT COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier,
|
|
PARAM_IN EIS_CONF_OPR_E eConfOpr)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEisData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
int i;
|
|
pVideoEisData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
for(i = 0; i < EIS_CHN_MAX_PORTS; i++) {
|
|
if(pVideoEisData->sPortBufSupplier[i].nPortIndex == pPortBufSupplier->nPortIndex)
|
|
break;
|
|
}
|
|
|
|
if (i == EIS_CHN_MAX_PORTS) {
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
} else {
|
|
switch (eConfOpr) {
|
|
case EIS_CHN_CONF_SET: {
|
|
memcpy(&pVideoEisData->sPortBufSupplier[i], pPortBufSupplier,
|
|
sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
|
|
} break;
|
|
case EIS_CHN_CONF_GET: {
|
|
memcpy(pPortBufSupplier, &pVideoEisData->sPortBufSupplier[i],
|
|
sizeof(COMP_PARAM_BUFFERSUPPLIERTYPE));
|
|
} break;
|
|
default: {
|
|
aloge("Wrong config operation[%d].", eConfOpr);
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE VideoEISGetConfig(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_INDEXTYPE nIndex,
|
|
PARAM_IN void *pComponentConfigStructure)
|
|
{
|
|
// VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
switch (nIndex) {
|
|
case COMP_IndexVendorEisChnAttr: {
|
|
eError = DoVideoEisChnConfigOpr(hComponent, (EIS_ATTR_S*)pComponentConfigStructure, EIS_CHN_CONF_GET);
|
|
} break;
|
|
|
|
case COMP_IndexVendorMPPChannelInfo: {
|
|
eError = DoVideoEisMPPChannelInfoOpr(hComponent, (MPP_CHN_S *)pComponentConfigStructure, EIS_CHN_CONF_GET);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisEnable: {
|
|
eError = DoVideoEisChnEnableOpr(hComponent, (int*)pComponentConfigStructure, EIS_CHN_CONF_GET);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisGetData: {
|
|
EIS_PARAMS_S *pData = (EIS_PARAMS_S *)pComponentConfigStructure;
|
|
eError = DoVideoEisGetData(hComponent, pData, pData->s32MilliSec);
|
|
} break;
|
|
|
|
case COMP_IndexVendorTunnelInfo: {
|
|
eError = DoVideoEisGetTunnelInfo(hComponent, (COMP_INTERNAL_TUNNELINFOTYPE *)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexParamPortDefinition: {
|
|
eError = DoVideoEisPortDefinitionOpr(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE *)pComponentConfigStructure, EIS_CHN_CONF_GET);
|
|
} break;
|
|
|
|
case COMP_IndexParamCompBufferSupplier: {
|
|
eError = DoVideoEisCompBufferSupplierOpr(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE *)pComponentConfigStructure, EIS_CHN_CONF_GET);
|
|
} break;
|
|
|
|
default: {
|
|
aloge("fatal error! unknown getConfig Index[0x%x]", nIndex);
|
|
eError = ERR_VI_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE VideoEISSetConfig(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_INDEXTYPE nIndex,
|
|
PARAM_IN void *pComponentConfigStructure)
|
|
{
|
|
// VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
switch (nIndex) {
|
|
case COMP_IndexVendorEisChnAttr: {
|
|
eError = DoVideoEisChnConfigOpr(hComponent, (EIS_ATTR_S*)pComponentConfigStructure, EIS_CHN_CONF_SET);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisAlgoModeAttr: {
|
|
eError = DoSetEisChnAlgoModeOpr(hComponent, (EIS_ALGO_MODE*)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisVFmtAttr: {
|
|
eError = DoSetEisChnVFmtOpr(hComponent, (EIS_VIDEO_FMT_ATTR_S*)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisDataProcAttr: {
|
|
eError = DoSetEisChnDataProcOpr(hComponent, (EIS_DATA_PROC_ATTR_S*)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisGyroAttr: {
|
|
eError = DoSetEisChnGyroOpr(hComponent, (EIS_GYRO_DATA_ATTR_S*)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisKmatAttr: {
|
|
eError = DoSetEisChnKmatOpr(hComponent, (EIS_KMAT_S*)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexVendorMPPChannelInfo: {
|
|
eError = DoVideoEisMPPChannelInfoOpr(hComponent, (MPP_CHN_S *)pComponentConfigStructure, EIS_CHN_CONF_SET);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisEnable: {
|
|
eError = DoVideoEisChnEnableOpr(hComponent, (int*)pComponentConfigStructure, EIS_CHN_CONF_SET);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisReleaseData: {
|
|
eError = DoVideoEisReleaseData(hComponent, (EIS_PARAMS_S *)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisStoreFrame: {
|
|
eError = DoVideoEisStoreFrameOpr(hComponent, (const char*)pComponentConfigStructure);
|
|
} break;
|
|
|
|
case COMP_IndexVendorEisFreq: {
|
|
eError = DoVideoEisFreqOpr(hComponent, (int*)pComponentConfigStructure, EIS_CHN_CONF_SET);
|
|
} break;
|
|
|
|
case COMP_IndexParamPortDefinition: {
|
|
eError = DoVideoEisPortDefinitionOpr(hComponent, (COMP_PARAM_PORTDEFINITIONTYPE *)pComponentConfigStructure, EIS_CHN_CONF_SET);
|
|
} break;
|
|
|
|
case COMP_IndexParamCompBufferSupplier: {
|
|
eError = DoVideoEisCompBufferSupplierOpr(hComponent, (COMP_PARAM_BUFFERSUPPLIERTYPE *)pComponentConfigStructure, EIS_CHN_CONF_SET);
|
|
} break;
|
|
|
|
default: {
|
|
aloge("Unknown EIS configuration index[0x%x]", nIndex);
|
|
eError = ERR_EIS_NOT_SUPPORT;
|
|
} break;
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE VideoEISComponentTunnelRequest(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN unsigned int nPort,
|
|
PARAM_IN COMP_HANDLETYPE hTunneledComp, PARAM_IN unsigned int nTunneledPort,
|
|
PARAM_INOUT COMP_TUNNELSETUPTYPE *pTunnelSetup)
|
|
{
|
|
ERRORTYPE eError = SUCCESS;
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
COMP_PARAM_PORTDEFINITIONTYPE *pPortDef;
|
|
COMP_INTERNAL_TUNNELINFOTYPE *pPortTunnelInfo;
|
|
COMP_PARAM_BUFFERSUPPLIERTYPE *pPortBufSupplier;
|
|
int i;
|
|
|
|
/* You can bind input ports and output ports,
|
|
*but better not do this in Executing state
|
|
*/
|
|
if (pVideoEISData->state == COMP_StateExecuting) {
|
|
alogw("Be careful! tunnel request may be some danger in StateExecuting");
|
|
} else if (pVideoEISData->state != COMP_StateIdle) {
|
|
aloge("Fatal error! tunnel request can't be in state[0x%x]",pVideoEISData->state);
|
|
eError = ERR_EIS_INCORRECT_STATE_OPERATION;
|
|
goto EBind;
|
|
}
|
|
|
|
for (i = 0; i < EIS_CHN_MAX_PORTS; ++i) {
|
|
if (pVideoEISData->sPortDef[i].nPortIndex == nPort) {
|
|
pPortDef = &pVideoEISData->sPortDef[i];
|
|
break;
|
|
}
|
|
}
|
|
if (i == EIS_CHN_MAX_PORTS) {
|
|
aloge("fatal error! portIndex[%d] wrong!", nPort);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
goto EBind;
|
|
}
|
|
|
|
for (i = 0; i < EIS_CHN_MAX_PORTS; ++i) {
|
|
if (pVideoEISData->sPortTunnelInfo[i].nPortIndex == nPort) {
|
|
pPortTunnelInfo = &pVideoEISData->sPortTunnelInfo[i];
|
|
break;
|
|
}
|
|
}
|
|
if (i == EIS_CHN_MAX_PORTS) {
|
|
aloge("fatal error! portIndex[%d] wrong!", nPort);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
goto EBind;
|
|
}
|
|
|
|
for (i = 0; i < EIS_CHN_MAX_PORTS; ++i) {
|
|
if (pVideoEISData->sPortBufSupplier[i].nPortIndex == nPort) {
|
|
pPortBufSupplier = &pVideoEISData->sPortBufSupplier[i];
|
|
break;
|
|
}
|
|
}
|
|
if (i == EIS_CHN_MAX_PORTS) {
|
|
aloge("fatal error! portIndex[%d] wrong!", nPort);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
goto EBind;
|
|
}
|
|
|
|
pPortTunnelInfo->nPortIndex = nPort;
|
|
pPortTunnelInfo->hTunnel = hTunneledComp;
|
|
pPortTunnelInfo->nTunnelPortIndex = nTunneledPort;
|
|
pPortTunnelInfo->eTunnelType =
|
|
(pPortDef->eDomain == COMP_PortDomainOther) ? TUNNEL_TYPE_CLOCK : TUNNEL_TYPE_COMMON;
|
|
/* When all the parameters is zero, we unbind it, it is a engage */
|
|
if(NULL == hTunneledComp && 0 == nTunneledPort && NULL == pTunnelSetup) {
|
|
alogd("Receive a cancel setup tunnel request on port[%d]", nPort);
|
|
pPortTunnelInfo->hTunnel = NULL;
|
|
|
|
if(pPortDef->eDir == COMP_DirOutput)
|
|
pVideoEISData->bOutputPortTunnelFlag = FALSE;
|
|
else if (pPortDef->eDir == COMP_DirInput)
|
|
pVideoEISData->bInputPortTunnelFlag = FALSE;
|
|
eError = SUCCESS;
|
|
goto EBind;
|
|
}
|
|
|
|
if(pPortDef->eDir == COMP_DirOutput) {
|
|
if (pVideoEISData->bOutputPortTunnelFlag) {
|
|
aloge("EIS component[%d] output port has already binded, why bind again?!",
|
|
pVideoEISData->mMppChnInfo.mChnId);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EBind;
|
|
}
|
|
pTunnelSetup->nTunnelFlags = 0;
|
|
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
|
|
pVideoEISData->bOutputPortTunnelFlag = TRUE;
|
|
} else if (pPortDef->eDir == COMP_DirInput && pVideoEISData->mEISAttr.bSimuOffline){
|
|
aloge("EIS component[%d] input port can't be bind in offline simulation mode.",
|
|
pVideoEISData->mMppChnInfo.mChnId);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EBind;
|
|
} else if (pPortDef->eDir == COMP_DirInput) {
|
|
if (pVideoEISData->bInputPortTunnelFlag) {
|
|
aloge("EIS component[%d] input port has already binded, why bind again?!",
|
|
pVideoEISData->mMppChnInfo.mChnId);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
goto EBind;
|
|
}
|
|
/* Check the data compatibility between the ports using one or more GetParameter calls. */
|
|
/* B checks if its input port is compatible with the output port of component A. */
|
|
COMP_PARAM_PORTDEFINITIONTYPE stTunnelPortDef;
|
|
stTunnelPortDef.nPortIndex = nTunneledPort;
|
|
COMP_GetConfig(hTunneledComp, COMP_IndexParamPortDefinition, &stTunnelPortDef);
|
|
if(stTunnelPortDef.eDir != COMP_DirOutput) {
|
|
aloge("Fatal error! you are binding a input tunnel port[index%d] to an input port[index%d].",
|
|
nTunneledPort, pPortDef->nPortIndex);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
goto EBind;
|
|
}
|
|
#if 0
|
|
if (strcmp((const char*)&pPortDef->format, (const char*)&stTunnelPortDef.format)) {
|
|
aloge("Fatal error! you are binding a output tunnel port[fmt%d] to an input port[fmt%d].",
|
|
stTunnelPortDef.format, pPortDef->format);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
goto EBind;
|
|
}
|
|
#endif
|
|
/* The component B informs component A about the final result of negotiation. */
|
|
if(pTunnelSetup->eSupplier != pPortBufSupplier->eBufferSupplier) {
|
|
alogw("Low probability! use input portIndex[%d] buffer supplier[%d] as final!",
|
|
nPort, pPortBufSupplier->eBufferSupplier);
|
|
pTunnelSetup->eSupplier = pPortBufSupplier->eBufferSupplier;
|
|
}
|
|
|
|
COMP_PARAM_BUFFERSUPPLIERTYPE oSupplier;
|
|
oSupplier.nPortIndex = nTunneledPort;
|
|
COMP_GetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
|
|
oSupplier.eBufferSupplier = pTunnelSetup->eSupplier;
|
|
COMP_SetConfig(hTunneledComp, COMP_IndexParamCompBufferSupplier, &oSupplier);
|
|
pVideoEISData->bInputPortTunnelFlag = TRUE;
|
|
}
|
|
|
|
EBind:
|
|
return eError;
|
|
}
|
|
|
|
static void DoVideoEisSendBackInputFrame
|
|
(VIDEOEISDATATYPE *pVideoEisData, VIDEO_FRAME_INFO_S *pFrameInfo)
|
|
{
|
|
COMP_BUFFERHEADERTYPE BufferHeader;
|
|
memset(&BufferHeader, 0, sizeof(COMP_BUFFERHEADERTYPE));
|
|
if (FALSE == pVideoEisData->bInputPortTunnelFlag) {
|
|
BufferHeader.pAppPrivate = pFrameInfo;
|
|
pVideoEisData->pCallbacks->EmptyBufferDone(pVideoEisData->hSelf, pVideoEisData->pAppData, &BufferHeader);
|
|
} else {
|
|
BufferHeader.pOutputPortPrivate = pFrameInfo;
|
|
MM_COMPONENTTYPE *pTunnelComp = (MM_COMPONENTTYPE *)pVideoEisData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_VIDEO_IN].hTunnel;
|
|
BufferHeader.nOutputPortIndex = pVideoEisData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_VIDEO_IN].nTunnelPortIndex;
|
|
COMP_FillThisBuffer(pTunnelComp, &BufferHeader);
|
|
}
|
|
alogv("Release input FrameId[%d].", pFrameInfo->mId);
|
|
}
|
|
|
|
static void DoVideoEisReturnBackAllInputFrames(VIDEOEISDATATYPE *pVideoEisData)
|
|
{
|
|
VIDEO_FRAME_INFO_S *pFrameInfo = NULL;
|
|
VIDEO_FRAME_INFO_S stFrameInfoRet;
|
|
|
|
while (1) {
|
|
pFrameInfo = VideoBufMgrGetAllValidUsingFrame(pVideoEisData->pInputBufMgr);
|
|
if (NULL == pFrameInfo)
|
|
break;
|
|
stFrameInfoRet = *pFrameInfo;
|
|
DoVideoEisSendBackInputFrame(pVideoEisData, &stFrameInfoRet);
|
|
}
|
|
alogw("Return all input frames done, EIS Chn[%d].", pVideoEisData->mMppChnInfo.mChnId);
|
|
}
|
|
|
|
ERRORTYPE VideoEISEmptyThisBuffer(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_BUFFERHEADERTYPE *pBuffer)
|
|
{
|
|
ERRORTYPE eError = SUCCESS;
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
|
|
pthread_mutex_lock(&pVideoEISData->mStateLock);
|
|
if (pVideoEISData->state != COMP_StateExecuting) {
|
|
alogw("Send frame when EIS component state[0x%x] isn not executing", pVideoEISData->state);
|
|
eError = ERR_EIS_NOT_PERM;
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
goto EState;
|
|
}
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
|
|
/* put data ptr to CapMgr_queue for tunnel or user mpi_get\release */
|
|
if (pBuffer->nInputPortIndex == pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].nPortIndex) {
|
|
VIDEO_FRAME_INFO_S *pVInputFrm = NULL;
|
|
|
|
if(pVideoEISData->bInputPortTunnelFlag)
|
|
pVInputFrm = (VIDEO_FRAME_INFO_S *)pBuffer->pOutputPortPrivate;
|
|
else
|
|
pVInputFrm = (VIDEO_FRAME_INFO_S *)pBuffer->pAppPrivate;
|
|
|
|
eError = VideoBufMgrPushFrame(pVideoEISData->pInputBufMgr, pVInputFrm);
|
|
if (eError != SUCCESS) {
|
|
aloge("Failed to push this frame, it will be droped\n");
|
|
eError = ERR_EIS_BUF_FULL;
|
|
goto EPushFrm;
|
|
}
|
|
|
|
alogv("VideoEisEmptyThisBuffer pushFrame process, %p.\r\n", pVInputFrm->VFrame.mpVirAddr[0]);
|
|
|
|
if (pVideoEISData->bWaitingInputFrmFlag) {
|
|
message_t msg;
|
|
msg.command = EisComp_InputFrameAvailable;
|
|
put_message(&pVideoEISData->cmd_queue, &msg);
|
|
}
|
|
} else if (pBuffer->nInputPortIndex == pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].nPortIndex) {
|
|
/* We accept gyro datas and ready to process it. */
|
|
EIS_GYRO_PACKET_S *pVInputGyroPkt = NULL;
|
|
if(pVideoEISData->bInputPortTunnelFlag)
|
|
pVInputGyroPkt = (EIS_GYRO_PACKET_S *)pBuffer->pOutputPortPrivate;
|
|
else
|
|
pVInputGyroPkt = (EIS_GYRO_PACKET_S *)pBuffer->pAppPrivate;
|
|
|
|
if (ring_buffer_full(pVideoEISData->GryoRingBufHd)) {
|
|
EIS_GYRO_PACKET_S stGyroPktOut;
|
|
aloge("Gyro ring buffer is full, drop the oldest gyro data.");
|
|
ring_buffer_out(pVideoEISData->GryoRingBufHd, &stGyroPktOut, pBuffer->nFilledLen);
|
|
}
|
|
ring_buffer_in(pVideoEISData->GryoRingBufHd, pVInputGyroPkt, pBuffer->nFilledLen);
|
|
} else {
|
|
aloge("fatal error! inputPortIndex[%d] match nothing!", pBuffer->nOutputPortIndex);
|
|
}
|
|
|
|
EPushFrm:
|
|
EState:
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE VideoEISFillThisBuffer(PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN COMP_BUFFERHEADERTYPE *pBuffer)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
ERRORTYPE eError = SUCCESS;
|
|
int ret;
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *) (((MM_COMPONENTTYPE*) hComponent)->pComponentPrivate);
|
|
COMP_INTERNAL_TUNNELINFOTYPE *pPortTunnelInfo = &pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_VIDEO_IN];
|
|
MM_COMPONENTTYPE *pInTunnelComp = (MM_COMPONENTTYPE*)pPortTunnelInfo->hTunnel;
|
|
|
|
/* First of all, this interface can be used only in bind mode. */
|
|
if (!pVideoEISData->bOutputPortTunnelFlag) {
|
|
aloge("You can not invoke this interface in non-tunnel out port mode.");
|
|
eError = ERR_EIS_NOT_PERM;
|
|
}
|
|
|
|
if (pBuffer->nOutputPortIndex == pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].nPortIndex
|
|
&& pInTunnelComp) {
|
|
VIDEO_FRAME_INFO_S *pstFrameInfo = pBuffer->pAppPrivate;
|
|
VideoFrameListInfo *pVFrmList;
|
|
bool bFindFlag = 0;
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
list_for_each_entry(pVFrmList, &pVideoEISData->mOutUsedList, mList)
|
|
{
|
|
if (pVFrmList->mFrame.mId == pstFrameInfo->mId ||
|
|
pVFrmList->mFrame.VFrame.mpVirAddr[0] == pstFrameInfo->VFrame.mpVirAddr[0]) {
|
|
bFindFlag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bFindFlag) {
|
|
list_move_tail(&pVFrmList->mList, &pVideoEISData->mOutIdleList);
|
|
pVideoEISData->iOutFrmIdleCnt++;
|
|
} else {
|
|
aloge("No such video frame Id[%d]VirAddr[%p] is using, please check it.",
|
|
pstFrameInfo->mId, pstFrameInfo->VFrame.mpVirAddr[0]);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
}
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
} else {
|
|
aloge("Fatal error! outputPortIndex[%d]!=[%d]", pBuffer->nOutputPortIndex, pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].nPortIndex);
|
|
}
|
|
|
|
return eError;
|
|
}
|
|
|
|
static void _EisTraverOutputBufPool(VIDEOEISDATATYPE *pVideoEISData)
|
|
{
|
|
VideoFrameListInfo* EisOutFrmTmp = NULL;
|
|
VideoFrameListInfo* EisOutFrmCur = NULL;
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
if (!list_empty(&pVideoEISData->mOutUsedList)) {
|
|
list_for_each_entry_safe(EisOutFrmCur, EisOutFrmTmp, &pVideoEISData->mOutUsedList, mList)
|
|
{
|
|
if (EisOutFrmCur) {
|
|
aloge("Release video input frame[%d], vir addr[%p][%p].", EisOutFrmCur->mFrame.mId,
|
|
EisOutFrmCur->mFrame.VFrame.mpVirAddr[0], EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
}
|
|
}
|
|
EisOutFrmCur = NULL;
|
|
}
|
|
|
|
if (!list_empty(&pVideoEISData->mOutValidList)) {
|
|
list_for_each_entry_safe(EisOutFrmCur, EisOutFrmTmp, &pVideoEISData->mOutValidList, mList)
|
|
{
|
|
if (EisOutFrmCur) {
|
|
aloge("Release video input frame[%d], vir addr[%p][%p].", EisOutFrmCur->mFrame.mId,
|
|
EisOutFrmCur->mFrame.VFrame.mpVirAddr[0], EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
}
|
|
}
|
|
EisOutFrmCur = NULL;
|
|
}
|
|
|
|
if (!list_empty(&pVideoEISData->mOutIdleList)) {
|
|
list_for_each_entry_safe(EisOutFrmCur, EisOutFrmTmp, &pVideoEISData->mOutIdleList, mList)
|
|
{
|
|
if (EisOutFrmCur) {
|
|
aloge("Release video input frame[%d], vir addr[%p][%p].", EisOutFrmCur->mFrame.mId,
|
|
EisOutFrmCur->mFrame.VFrame.mpVirAddr[0], EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
}
|
|
}
|
|
EisOutFrmCur = NULL;
|
|
}
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
}
|
|
|
|
ERRORTYPE _EisCreateOutputBufPool(VIDEOEISDATATYPE *pVideoEISData)
|
|
{
|
|
int i = 0;
|
|
int iPoolBufNum = pVideoEISData->mEISAttr.iOutputBufBum;
|
|
VideoFrameListInfo* EisOutFrm;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
pthread_mutex_init(&pVideoEISData->mOutFrmListLock, NULL);
|
|
INIT_LIST_HEAD(&pVideoEISData->mOutIdleList);
|
|
INIT_LIST_HEAD(&pVideoEISData->mOutValidList);
|
|
INIT_LIST_HEAD(&pVideoEISData->mOutUsedList);
|
|
for (i = 0; i < iPoolBufNum; i++) {
|
|
/* alloc size for output buffers */
|
|
EisOutFrm = malloc(sizeof(VideoFrameListInfo));
|
|
if (NULL == EisOutFrm)
|
|
continue;
|
|
EisOutFrm->mFrame.VFrame.mpVirAddr[0] = ion_allocMem(
|
|
pVideoEISData->mEISAttr.iVideoOutWidth*pVideoEISData->mEISAttr.iVideoOutHeight);
|
|
EisOutFrm->mFrame.VFrame.mpVirAddr[1] = ion_allocMem(
|
|
pVideoEISData->mEISAttr.iVideoOutWidth*pVideoEISData->mEISAttr.iVideoOutHeight/2);
|
|
EisOutFrm->mFrame.VFrame.mPhyAddr[0] = ion_getMemPhyAddr(EisOutFrm->mFrame.VFrame.mpVirAddr[0]);
|
|
EisOutFrm->mFrame.VFrame.mPhyAddr[1] = ion_getMemPhyAddr(EisOutFrm->mFrame.VFrame.mpVirAddr[1]);
|
|
EisOutFrm->mFrame.VFrame.mWidth = pVideoEISData->mEISAttr.iVideoOutWidth;
|
|
EisOutFrm->mFrame.VFrame.mHeight = pVideoEISData->mEISAttr.iVideoOutHeight;
|
|
EisOutFrm->mFrame.VFrame.mOffsetTop = 0;
|
|
EisOutFrm->mFrame.VFrame.mOffsetLeft = 0;
|
|
EisOutFrm->mFrame.VFrame.mOffsetRight = pVideoEISData->mEISAttr.iVideoOutWidth;
|
|
EisOutFrm->mFrame.VFrame.mOffsetBottom = pVideoEISData->mEISAttr.iVideoOutHeight;
|
|
EisOutFrm->mFrame.VFrame.mField = VIDEO_FIELD_FRAME;
|
|
EisOutFrm->mFrame.VFrame.mVideoFormat = VIDEO_FORMAT_LINEAR;
|
|
EisOutFrm->mFrame.VFrame.mCompressMode = COMPRESS_MODE_NONE;
|
|
|
|
EisOutFrm->mFrame.VFrame.mStride[0] = 0;
|
|
EisOutFrm->mFrame.VFrame.mStride[1] = 0;
|
|
EisOutFrm->mFrame.VFrame.mStride[2] = 0;
|
|
EisOutFrm->mFrame.VFrame.mPixelFormat = pVideoEISData->mEISAttr.eVideoFmt;
|
|
EisOutFrm->mFrame.mId = pVideoEISData->iOutFrmCnt;
|
|
list_add_tail(&EisOutFrm->mList, &pVideoEISData->mOutIdleList);
|
|
pVideoEISData->iOutFrmCnt++;
|
|
}
|
|
pVideoEISData->iOutFrmIdleCnt = pVideoEISData->iOutFrmCnt;
|
|
|
|
// _EisTraverOutputBufPool(pVideoEISData);
|
|
|
|
return eError;
|
|
}
|
|
|
|
void _EisDestroyOutputBufPool(VIDEOEISDATATYPE *pVideoEISData)
|
|
{
|
|
VideoFrameListInfo* EisOutFrmTmp = NULL;
|
|
VideoFrameListInfo* EisOutFrmCur = NULL;
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
if (!list_empty(&pVideoEISData->mOutUsedList)) {
|
|
list_for_each_entry_safe(EisOutFrmCur, EisOutFrmTmp, &pVideoEISData->mOutUsedList, mList)
|
|
{
|
|
if (EisOutFrmCur) {
|
|
aloge("Release video input frame[%d], vir addr[%p][%p].", EisOutFrmCur->mFrame.mId,
|
|
EisOutFrmCur->mFrame.VFrame.mpVirAddr[0], EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
ion_freeMem(EisOutFrmCur->mFrame.VFrame.mpVirAddr[0]);
|
|
ion_freeMem(EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
free(EisOutFrmCur);
|
|
}
|
|
}
|
|
EisOutFrmCur = NULL;
|
|
}
|
|
|
|
if (!list_empty(&pVideoEISData->mOutValidList)) {
|
|
list_for_each_entry_safe(EisOutFrmCur, EisOutFrmTmp, &pVideoEISData->mOutValidList, mList)
|
|
{
|
|
if (EisOutFrmCur) {
|
|
aloge("Release video input frame[%d], vir addr[%p][%p].", EisOutFrmCur->mFrame.mId,
|
|
EisOutFrmCur->mFrame.VFrame.mpVirAddr[0], EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
ion_freeMem(EisOutFrmCur->mFrame.VFrame.mpVirAddr[0]);
|
|
ion_freeMem(EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
free(EisOutFrmCur);
|
|
}
|
|
}
|
|
EisOutFrmCur = NULL;
|
|
}
|
|
|
|
if (!list_empty(&pVideoEISData->mOutIdleList)) {
|
|
list_for_each_entry_safe(EisOutFrmCur, EisOutFrmTmp, &pVideoEISData->mOutIdleList, mList)
|
|
{
|
|
if (EisOutFrmCur) {
|
|
aloge("Release video input frame[%d], vir addr[%p][%p].", EisOutFrmCur->mFrame.mId,
|
|
EisOutFrmCur->mFrame.VFrame.mpVirAddr[0], EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
ion_freeMem(EisOutFrmCur->mFrame.VFrame.mpVirAddr[0]);
|
|
ion_freeMem(EisOutFrmCur->mFrame.VFrame.mpVirAddr[1]);
|
|
free(EisOutFrmCur);
|
|
}
|
|
}
|
|
EisOutFrmCur = NULL;
|
|
}
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
|
|
pthread_mutex_destroy(&pVideoEISData->mOutFrmListLock);
|
|
}
|
|
|
|
static void _EisDumpHardwareLibConfigs(EISE_CFG_PARA *pEisCfg)
|
|
{
|
|
printf("Dump EIS hardware driver config:\r\n");
|
|
printf("\t in_w:\t%d\r\n", pEisCfg->in_w);
|
|
printf("\t in_h:\t%d\r\n", pEisCfg->in_h);
|
|
printf("\t out_h:\t%d\r\n", pEisCfg->out_h);
|
|
printf("\t out_w:\t%d\r\n", pEisCfg->out_w);
|
|
printf("\t hor_off:\t%d\r\n", pEisCfg->hor_off);
|
|
printf("\t vor_off:\t%d\r\n", pEisCfg->ver_off);
|
|
|
|
if (pEisCfg->in_yuv_type == PLANE_YUV420) {
|
|
printf("\t in_yuv_type:\tYUV420\r\n");
|
|
} else if (pEisCfg->in_yuv_type == PLANE_YVU420) {
|
|
printf("\t in_yuv_type:\tYVU420\r\n");
|
|
}
|
|
|
|
if (pEisCfg->out_yuv_type == PLANE_YUV420)
|
|
printf("\t out_yuv_type:\tYUV420\r\n");
|
|
else if (pEisCfg->out_yuv_type == PLANE_YVU420)
|
|
printf("\t out_yuv_type:\tYVU420\r\n");
|
|
|
|
printf("\t in_luma_pitch:\t%d\r\n", pEisCfg->in_luma_pitch);
|
|
printf("\t in_chroma_pitch:\t%d\r\n", pEisCfg->in_chroma_pitch);
|
|
printf("\t out_luma_pitch:\t%d\r\n", pEisCfg->out_luma_pitch);
|
|
printf("\t out_chroma_pitch:\t%d\r\n", pEisCfg->out_chroma_pitch);
|
|
printf("\t src_width:\t%d\r\n", pEisCfg->src_width);
|
|
printf("\t src_height:\t%d\r\n", pEisCfg->src_height);
|
|
printf("\t cut_height:\t%d\r\n", pEisCfg->cut_height);
|
|
printf("\t rt:\t%f\r\n", pEisCfg->rt);
|
|
printf("\t k_matrix[0]:\t%f\r\n", pEisCfg->k_matrix[0]);
|
|
printf("\t k_matrix[1]:\t%f\r\n", pEisCfg->k_matrix[2]);
|
|
printf("\t k_matrix[2]:\t%f\r\n", pEisCfg->k_matrix[4]);
|
|
printf("\t k_matrix[3]:\t%f\r\n", pEisCfg->k_matrix[5]);
|
|
|
|
printf("\t k_matrix[8]:\t%f\r\n", pEisCfg->k_matrix[8]);
|
|
printf("\t ts:\t%f\r\n", pEisCfg->ts);
|
|
printf("\t td:\t%f\r\n", pEisCfg->td);
|
|
printf("\t stable_anglev[0]:\t%f\r\n", pEisCfg->stable_anglev[0]);
|
|
printf("\t stable_anglev[1]:\t%f\r\n", pEisCfg->stable_anglev[1]);
|
|
printf("\t stable_anglev[2]:\t%f\r\n", pEisCfg->stable_anglev[2]);
|
|
|
|
printf("\t angle_th[0]:\t%f\r\n", pEisCfg->angle_th[0]);
|
|
printf("\t angle_th[1]:\t%f\r\n", pEisCfg->angle_th[1]);
|
|
printf("\t angle_th[2]:\t%f\r\n", pEisCfg->angle_th[2]);
|
|
|
|
printf("\t radius[0]:\t%d\r\n", pEisCfg->radius[0]);
|
|
printf("\t radius[1]:\t%d\r\n", pEisCfg->radius[1]);
|
|
printf("\t radius[2]:\t%d\r\n", pEisCfg->radius[2]);
|
|
|
|
printf("\t video fps:\t%d\r\n", pEisCfg->fps);
|
|
printf("\t filter_type:\t%d\r\n", pEisCfg->filter_type);
|
|
printf("\t xy_exchange_en:\t%d\r\n", pEisCfg->xy_exchange_en);
|
|
printf("\t rolling_shutter:\t%d\r\n", pEisCfg->rolling_shutter);
|
|
printf("\t rs_correction_en:\t%d\r\n", pEisCfg->rs_correction_en);
|
|
printf("\t frame_rotation_en:\t%d\r\n", pEisCfg->frame_rotation_en);
|
|
printf("\t fast_mode:\t%d\r\n", pEisCfg->fast_mode);
|
|
printf("\t g_en_angle_filter:\t%d\r\n", pEisCfg->g_en_angle_filter);
|
|
printf("\t g_interlace:\t%d\r\n", pEisCfg->g_interlace);
|
|
printf("\t max_frm_buf:\t%d\r\n", pEisCfg->max_frm_buf);
|
|
printf("\t max_next_frm:\t%d\r\n", pEisCfg->max_next_frm);
|
|
}
|
|
|
|
static void VideoEisSetHwCfgs(VIDEOEISDATATYPE *pVideoEISData)
|
|
{
|
|
pVideoEISData->mEisCfg.in_w = pVideoEISData->mEISAttr.iVideoInWidth;
|
|
pVideoEISData->mEisCfg.in_h = pVideoEISData->mEISAttr.iVideoInHeight;
|
|
|
|
// 1080p@30fps
|
|
pVideoEISData->mEisCfg.out_h = pVideoEISData->mEISAttr.iVideoOutHeight;
|
|
pVideoEISData->mEisCfg.out_w = pVideoEISData->mEISAttr.iVideoOutWidth;
|
|
pVideoEISData->mEisCfg.hor_off = (int)((float)(pVideoEISData->mEISAttr.iVideoInWidth-pVideoEISData->mEISAttr.iVideoOutWidth)/64+0.5)*32;
|
|
pVideoEISData->mEisCfg.ver_off = (int)((float)(pVideoEISData->mEISAttr.iVideoInHeight-pVideoEISData->mEISAttr.iVideoOutHeight)/64+0.5)*32;
|
|
pVideoEISData->mEisCfg.in_yuv_type =
|
|
(pVideoEISData->mEISAttr.eVideoFmt == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420) ? PLANE_YUV420 : PLANE_YVU420;
|
|
pVideoEISData->mEisCfg.out_yuv_type =
|
|
(pVideoEISData->mEISAttr.eVideoFmt == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420) ? PLANE_YUV420 : PLANE_YVU420;
|
|
pVideoEISData->mEisCfg.in_luma_pitch = pVideoEISData->mEISAttr.iVideoInWidth;
|
|
pVideoEISData->mEisCfg.in_chroma_pitch = pVideoEISData->mEISAttr.iVideoInWidth;
|
|
pVideoEISData->mEisCfg.out_luma_pitch = pVideoEISData->mEISAttr.iVideoOutWidth;
|
|
pVideoEISData->mEisCfg.out_chroma_pitch = pVideoEISData->mEISAttr.iVideoOutWidth;
|
|
|
|
switch (pVideoEISData->mEISAttr.eOperationMode) {
|
|
/* Just all use EIS_OPR_1080P30 configuration until now. */
|
|
case EIS_OPR_4K30: {
|
|
pVideoEISData->mEisCfg.src_width = 4032;
|
|
pVideoEISData->mEisCfg.src_height = 2256;
|
|
pVideoEISData->mEisCfg.cut_height = 2256;
|
|
pVideoEISData->mEisCfg.rt = (float)4296 / (300*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 2478.96f;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 1983.4f;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 2486.28f;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 1165.32f;
|
|
pVideoEISData->iVideoLineTime = 30;
|
|
pVideoEISData->mEisCfg.g_interlace = 1;
|
|
} break;
|
|
case EIS_OPR_2P7K30: {
|
|
pVideoEISData->mEisCfg.src_width = 3840;
|
|
pVideoEISData->mEisCfg.src_height = 2160;
|
|
pVideoEISData->mEisCfg.cut_height = 2160;
|
|
pVideoEISData->mEisCfg.rt = (float)4296 / (300*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 1960.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 1680.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 1960.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 944.0f;
|
|
pVideoEISData->iVideoLineTime = 30;
|
|
pVideoEISData->mEisCfg.g_interlace = 1;
|
|
} break;
|
|
case EIS_OPR_VGA30: {
|
|
pVideoEISData->mEisCfg.src_width = 3840;
|
|
pVideoEISData->mEisCfg.src_height = 2160;
|
|
pVideoEISData->mEisCfg.cut_height = 2160;
|
|
pVideoEISData->mEisCfg.rt = (float)4296 / (300*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 466.67f;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 400.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 466.67f;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 224.0f;
|
|
pVideoEISData->iVideoLineTime = 30;
|
|
pVideoEISData->mEisCfg.g_interlace = 1;
|
|
} break;
|
|
case EIS_OPR_1080P30: {
|
|
pVideoEISData->mEisCfg.src_width = 3840;
|
|
pVideoEISData->mEisCfg.src_height = 2160;
|
|
pVideoEISData->mEisCfg.cut_height = 2160;
|
|
pVideoEISData->mEisCfg.rt = (float)4296 / (300*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 1400.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 1200.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 1400.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 672.0f;
|
|
pVideoEISData->iVideoLineTime = 30;
|
|
pVideoEISData->mEisCfg.g_interlace = 1;
|
|
} break; /* keep default settings */
|
|
case EIS_OPR_VGA60: {
|
|
pVideoEISData->mEisCfg.src_width = 2016;
|
|
pVideoEISData->mEisCfg.src_height = 1128;
|
|
pVideoEISData->mEisCfg.cut_height = 1128;
|
|
pVideoEISData->mEisCfg.rt = (float)2256 / (294*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 467.82f;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 400.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 467.82f;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 224.0f;
|
|
pVideoEISData->iVideoLineTime = 9;
|
|
pVideoEISData->mEisCfg.g_interlace = 2;
|
|
} break;
|
|
case EIS_OPR_1080P60: {
|
|
pVideoEISData->mEisCfg.src_width = 2016;
|
|
pVideoEISData->mEisCfg.src_height = 1128;
|
|
pVideoEISData->mEisCfg.cut_height = 1128;
|
|
pVideoEISData->mEisCfg.rt = (float)2256 / (294*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 1400.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 1008.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 1400.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 564.0f;
|
|
pVideoEISData->iVideoLineTime = 9;
|
|
pVideoEISData->mEisCfg.g_interlace = 2;
|
|
} break;
|
|
case EIS_OPR_DEBUG_RES: {
|
|
pVideoEISData->mEisCfg.src_width = 3840;
|
|
pVideoEISData->mEisCfg.src_height = 2160;
|
|
pVideoEISData->mEisCfg.cut_height = 2160;
|
|
pVideoEISData->mEisCfg.rt = (float)4296 / (300*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 1680.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 1440.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 1680.0f;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 816.0f;
|
|
pVideoEISData->iVideoLineTime = 30;
|
|
} break;
|
|
default: {
|
|
pVideoEISData->mEisCfg.src_width = 3840;
|
|
pVideoEISData->mEisCfg.src_height = 2160;
|
|
pVideoEISData->mEisCfg.cut_height = 2160;
|
|
pVideoEISData->mEisCfg.rt = (float)4296 / (300*1000*1000);
|
|
pVideoEISData->mEisCfg.k_matrix[0] = 3735.99;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = 1188.06;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = 3665.66;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = 680.34;
|
|
pVideoEISData->iVideoLineTime = 30;
|
|
pVideoEISData->mEisCfg.g_interlace = 1;
|
|
|
|
aloge("You set a wrong operation mode[%d], use EIS_OPR_1080P30 by default.", pVideoEISData->mEISAttr.eOperationMode);
|
|
} break;
|
|
}
|
|
|
|
if (pVideoEISData->mEISAttr.bUseKmat) {
|
|
pVideoEISData->mEisCfg.k_matrix[0] = pVideoEISData->mEISAttr.stEisKmat.KmatK1;
|
|
pVideoEISData->mEisCfg.k_matrix[2] = pVideoEISData->mEISAttr.stEisKmat.KmatK2;
|
|
pVideoEISData->mEisCfg.k_matrix[4] = pVideoEISData->mEISAttr.stEisKmat.KmatKx;
|
|
pVideoEISData->mEisCfg.k_matrix[5] = pVideoEISData->mEISAttr.stEisKmat.KmatKy;
|
|
}
|
|
|
|
pVideoEISData->mEisCfg.k_matrix[8] = 1;
|
|
pVideoEISData->mEisCfg.ts = (float)pVideoEISData->mEisCfg.cut_height * pVideoEISData->mEisCfg.rt;
|
|
pVideoEISData->mEisCfg.td = 0;
|
|
// (float)(pVideoEISData->mEisCfg.src_height - pVideoEISData->mEisCfg.cut_height)/2*pVideoEISData->mEisCfg.rt;
|
|
#if 1
|
|
pVideoEISData->mEisCfg.stable_anglev[0] = 0.06155;
|
|
pVideoEISData->mEisCfg.stable_anglev[1] = 0.015;
|
|
pVideoEISData->mEisCfg.stable_anglev[2] = -0.0173;
|
|
#else
|
|
pVideoEISData->mEisCfg.stable_anglev[0] = 0.0082;
|
|
pVideoEISData->mEisCfg.stable_anglev[1] = -0.0052;
|
|
pVideoEISData->mEisCfg.stable_anglev[2] = -0.0155;
|
|
#endif
|
|
|
|
#ifndef PI
|
|
#define PI 3.141592653589793
|
|
#endif
|
|
|
|
pVideoEISData->mEisCfg.angle_th[0] = 0;
|
|
pVideoEISData->mEisCfg.angle_th[1] = 0;
|
|
pVideoEISData->mEisCfg.angle_th[2] = 2*PI/180;
|
|
|
|
switch(pVideoEISData->mEisCfg.out_w)
|
|
{
|
|
case 2688:
|
|
case 2304:
|
|
pVideoEISData->mEisCfg.radius[0] = 17;
|
|
pVideoEISData->mEisCfg.radius[1] = 2;
|
|
pVideoEISData->mEisCfg.radius[2] = 1;
|
|
pVideoEISData->mEisCfg.max_frm_buf = pVideoEISData->mEISAttr.iEisFilterWidth;
|
|
pVideoEISData->mEisCfg.filter_type = 0; // 0:EIS_LOWPASS; 1:EIS_AVERAGE 2:EIS_POLYFIT1
|
|
pVideoEISData->mEisCfg.g_en_angle_filter = 0;
|
|
break;
|
|
case 1600:
|
|
case 1920:
|
|
//pVideoEISData->mEisCfg.radius[0] = 17;
|
|
//pVideoEISData->mEisCfg.radius[1] = 2;
|
|
//pVideoEISData->mEisCfg.radius[2] = 1;
|
|
//pVideoEISData->mEisCfg.max_frm_buf = pVideoEISData->mEISAttr.iEisFilterWidth;
|
|
//pVideoEISData->mEisCfg.filter_type = 0; // 0:EIS_LOWPASS; 1:EIS_AVERAGE 2:EIS_POLYFIT1
|
|
//pVideoEISData->mEisCfg.g_en_angle_filter = 0;
|
|
pVideoEISData->mEisCfg.radius[1] = 2;
|
|
pVideoEISData->mEisCfg.radius[2] = 1;
|
|
pVideoEISData->mEisCfg.radius[0] = pVideoEISData->mEISAttr.iEisFilterWidth
|
|
-pVideoEISData->mEisCfg.radius[1]-pVideoEISData->mEisCfg.radius[2];
|
|
if (pVideoEISData->mEisCfg.radius[0] < pVideoEISData->mEisCfg.radius[1]) {
|
|
aloge("You set a wrong input buffer[%d], use [%d] by default.", pVideoEISData->mEisCfg.radius[1]);
|
|
pVideoEISData->mEisCfg.radius[0] = pVideoEISData->mEisCfg.radius[1];
|
|
}
|
|
break;
|
|
case 640:
|
|
default:
|
|
pVideoEISData->mEisCfg.radius[0] = 17;
|
|
pVideoEISData->mEisCfg.radius[1] = 1;
|
|
pVideoEISData->mEisCfg.radius[2] = 0;
|
|
pVideoEISData->mEisCfg.max_frm_buf = pVideoEISData->mEISAttr.iEisFilterWidth > 4 ? 4 : pVideoEISData->mEISAttr.iEisFilterWidth;
|
|
pVideoEISData->mEisCfg.filter_type = 0; // 0:EIS_LOWPASS; 1:EIS_AVERAGE 2:EIS_POLYFIT1
|
|
pVideoEISData->mEisCfg.g_en_angle_filter = 0;
|
|
break;
|
|
}
|
|
|
|
if (pVideoEISData->mEISAttr.iInputBufNum < pVideoEISData->mEISAttr.iEisFilterWidth)
|
|
pVideoEISData->mEISAttr.bRetInFrmFast = 1;
|
|
|
|
if (pVideoEISData->mEISAttr.bVerticalFlip && pVideoEISData->mEISAttr.bHorizFlip) {
|
|
pVideoEISData->mEisPrivAttr.fGyroAxScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAyScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAzScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor = 1;
|
|
} else if (!pVideoEISData->mEISAttr.bVerticalFlip && pVideoEISData->mEISAttr.bHorizFlip) {
|
|
pVideoEISData->mEisPrivAttr.fGyroAxScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAyScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAzScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor = -1;
|
|
} else if (pVideoEISData->mEISAttr.bVerticalFlip && !pVideoEISData->mEISAttr.bHorizFlip) {
|
|
pVideoEISData->mEisPrivAttr.fGyroAxScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAyScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAzScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor = -1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor = -1;
|
|
} else if (!pVideoEISData->mEISAttr.bVerticalFlip && !pVideoEISData->mEISAttr.bHorizFlip) {
|
|
pVideoEISData->mEisPrivAttr.fGyroAxScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAyScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroAzScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor = 1;
|
|
pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor = 1;
|
|
}
|
|
|
|
pVideoEISData->mEisCfg.fps = pVideoEISData->mEISAttr.iVideoFps;
|
|
pVideoEISData->mEisCfg.xy_exchange_en = 1;
|
|
pVideoEISData->mEisCfg.rolling_shutter = 0;
|
|
pVideoEISData->mEisCfg.fast_mode = 0;
|
|
if (pVideoEISData->mEISAttr.eOperationMode == EIS_OPR_VGA30 || pVideoEISData->mEISAttr.eOperationMode == EIS_OPR_VGA60) {
|
|
pVideoEISData->mEisCfg.filter_type = 0;
|
|
pVideoEISData->mEisCfg.g_en_angle_filter = 0;
|
|
pVideoEISData->mEisCfg.max_frm_buf = 1 + pVideoEISData->mEisCfg.radius[1] + pVideoEISData->mEisCfg.radius[2];
|
|
pVideoEISData->mEisCfg.max_next_frm = pVideoEISData->mEisCfg.max_frm_buf - pVideoEISData->mEisCfg.radius[1] - pVideoEISData->mEisCfg.radius[2];
|
|
} else if(pVideoEISData->mEISAttr.eOperationMode == EIS_OPR_1080P30 || pVideoEISData->mEISAttr.eOperationMode == EIS_OPR_1080P60){
|
|
pVideoEISData->mEisCfg.filter_type = 0;
|
|
pVideoEISData->mEisCfg.g_en_angle_filter = 0;
|
|
pVideoEISData->mEisCfg.max_frm_buf = pVideoEISData->mEisCfg.radius[0] + pVideoEISData->mEisCfg.radius[1] + pVideoEISData->mEisCfg.radius[2];
|
|
pVideoEISData->mEisCfg.max_next_frm = pVideoEISData->mEisCfg.max_frm_buf - pVideoEISData->mEisCfg.radius[1] - pVideoEISData->mEisCfg.radius[2];
|
|
}else {
|
|
pVideoEISData->mEisCfg.max_next_frm = pVideoEISData->mEisCfg.max_frm_buf - pVideoEISData->mEisCfg.radius[1] - pVideoEISData->mEisCfg.radius[2];
|
|
}
|
|
|
|
pVideoEISData->mEisCfg.rs_correction_en = 1; /* Only when frame_rotation_en == 1, it make sense. */
|
|
pVideoEISData->mEisCfg.frame_rotation_en = 1;
|
|
pVideoEISData->mEisCfg.old_radius_th0 = 3;
|
|
pVideoEISData->mEisCfg.old_radius_th1 = 5;
|
|
|
|
_EisDumpHardwareLibConfigs(&pVideoEISData->mEisCfg);
|
|
}
|
|
#if 0
|
|
static void _EisDumpSoftwareLibConfigs(EISE_CFG_PARA *pEisCfg)
|
|
{
|
|
printf("Dump EIS hardware driver config:\r\n");
|
|
printf("\t in_w:\t%d\r\n", pEisCfg->in_w);
|
|
printf("\t in_h:\t%d\r\n", pEisCfg->in_h);
|
|
printf("\t out_h:\t%d\r\n", pEisCfg->out_h[0]);
|
|
printf("\t out_w:\t%d\r\n", pEisCfg->out_w[0]);
|
|
|
|
if (pEisCfg->in_yuv_type == YUV420) {
|
|
printf("\t in_yuv_type:\tYUV420\r\n");
|
|
} else if (pEisCfg->in_yuv_type == YVU420) {
|
|
printf("\t in_yuv_type:\tYVU420\r\n");
|
|
}
|
|
|
|
if (pEisCfg->out_yuv_type == YUV420) {
|
|
printf("\t out_yuv_type:\tYUV420\r\n");
|
|
} else if (pEisCfg->out_yuv_type == YVU420) {
|
|
printf("\t out_yuv_type:\tYVU420\r\n");
|
|
}
|
|
printf("\t in_luma_pitch:\t%d\r\n", pEisCfg->in_luma_pitch);
|
|
printf("\t in_chroma_pitch:\t%d\r\n", pEisCfg->in_chroma_pitch);
|
|
printf("\t out_luma_pitch:\t%d\r\n", pEisCfg->out_luma_pitch[0]);
|
|
printf("\t out_chroma_pitch:\t%d\r\n", pEisCfg->out_chroma_pitch[0]);
|
|
printf("\t input_width:\t%d\r\n", pEisCfg->input_width);
|
|
printf("\t output_width:\t%d\r\n", pEisCfg->output_width);
|
|
printf("\t output_height:\t%d\r\n", pEisCfg->output_height);
|
|
printf("\t src_width:\t%d\r\n", pEisCfg->src_width);
|
|
printf("\t src_height:\t%d\r\n", pEisCfg->src_height);
|
|
printf("\t cut_height:\t%d\r\n", pEisCfg->cut_height);
|
|
printf("\t rt:\t%f\r\n", pEisCfg->rt);
|
|
printf("\t k_matrix[0]:\t%f\r\n", pEisCfg->k_matrix[0]);
|
|
printf("\t k_matrix[1]:\t%f\r\n", pEisCfg->k_matrix[1]);
|
|
printf("\t k_matrix[2]:\t%f\r\n", pEisCfg->k_matrix[2]);
|
|
printf("\t k_matrix[3]:\t%f\r\n", pEisCfg->k_matrix[3]);
|
|
|
|
printf("\t k_matrix[8]:\t%f\r\n", pEisCfg->k_matrix[8]);
|
|
printf("\t ts:\t%f\r\n", pEisCfg->ts);
|
|
printf("\t td:\t%f\r\n", pEisCfg->td);
|
|
printf("\t stable_anglev[0]:\t%f\r\n", pEisCfg->stable_anglev[0]);
|
|
printf("\t stable_anglev[1]:\t%f\r\n", pEisCfg->stable_anglev[1]);
|
|
printf("\t stable_anglev[2]:\t%f\r\n", pEisCfg->stable_anglev[2]);
|
|
|
|
printf("\t angle_th[0]:\t%f\r\n", pEisCfg->angle_th[0]);
|
|
printf("\t angle_th[1]:\t%f\r\n", pEisCfg->angle_th[1]);
|
|
printf("\t angle_th[2]:\t%f\r\n", pEisCfg->angle_th[2]);
|
|
|
|
printf("\t radius[0]:\t%d\r\n", pEisCfg->radius[0]);
|
|
printf("\t radius[1]:\t%d\r\n", pEisCfg->radius[1]);
|
|
printf("\t radius[2]:\t%d\r\n", pEisCfg->radius[2]);
|
|
|
|
printf("\t filter_type:\t%d\r\n", pEisCfg->filter_type);
|
|
printf("\t xy_exchange_en:\t%d\r\n", pEisCfg->xy_exchange_en);
|
|
printf("\t rolling_shutter:\t%d\r\n", pEisCfg->rolling_shutter);
|
|
}
|
|
|
|
static void VideoEisSetSwCfgs(VIDEOEISDATATYPE *pVideoEISData)
|
|
{
|
|
float KmatK1 = 1680.0f;
|
|
float KmatK2 = 1583.6f;
|
|
float KmatKx = 1502.2f;
|
|
float KmatKy = 863.9f;
|
|
|
|
pVideoEISData->mSwEISCfg.frame_width = 2496;
|
|
pVideoEISData->mSwEISCfg.frame_height = 1408;
|
|
pVideoEISData->mSwEISCfg.frame_out2_width = 0;
|
|
pVideoEISData->mSwEISCfg.frame_out2_height = 0;
|
|
pVideoEISData->mSwEISCfg.frame_width_stride = 2496;
|
|
pVideoEISData->mSwEISCfg.frame_height_stride = 1408;
|
|
pVideoEISData->mSwEISCfg.max_yaw_degrees = 8.5f;
|
|
pVideoEISData->mSwEISCfg.max_pitch_degrees = 4.5f;
|
|
pVideoEISData->mSwEISCfg.max_roll_degrees = 1.6f;
|
|
pVideoEISData->mSwEISCfg.output_scale = 1.0;
|
|
pVideoEISData->mSwEISCfg.gyro_frequency_in_Hz = (float)pVideoEISData->mEISAttr.iGyroFreq;
|
|
pVideoEISData->mSwEISCfg.target_fps = 30.0f;
|
|
pVideoEISData->mSwEISCfg.number_of_input_buffers = 5;
|
|
pVideoEISData->mSwEISCfg.number_of_output_buffers = pVideoEISData->mEISAttr.iOutputBufBum;
|
|
pVideoEISData->mSwEISCfg.operation_mode = 3;
|
|
pVideoEISData->mSwEISCfg.style = 0; //0:normal 1:motion-less
|
|
|
|
switch (pVideoEISData->mEISAttr.iOperationMode) {
|
|
case 3:
|
|
case 13: {
|
|
pVideoEISData->mSwEISCfg.frame_width = 2496;
|
|
pVideoEISData->mSwEISCfg.frame_height = 1408;
|
|
pVideoEISData->mSwEISCfg.frame_width_stride = 2496;
|
|
pVideoEISData->mSwEISCfg.frame_height_stride = 1408;
|
|
pVideoEISData->mSwEISCfg.max_yaw_degrees = 8.5f;
|
|
pVideoEISData->mSwEISCfg.max_pitch_degrees = 4.5f;
|
|
pVideoEISData->mSwEISCfg.max_roll_degrees = 1.6f;
|
|
pVideoEISData->mSwEISCfg.target_fps = 30.0f;
|
|
pVideoEISData->mSwEISCfg.number_of_input_buffers =
|
|
(pVideoEISData->mEISAttr.iOperationMode == 3) ? 5 : 27;
|
|
pVideoEISData->mSwEISCfg.operation_mode = pVideoEISData->mEISAttr.iOperationMode;
|
|
} break;
|
|
}
|
|
|
|
pVideoEISData->mSwEISCfg.frame_height
|
|
|
|
_EisDumpSoftwareLibConfigs(&pVideoEISData->mEisCfg);
|
|
}
|
|
#endif
|
|
|
|
//#define DEBUG_GYRO_BUFFER
|
|
#ifdef DEBUG_GYRO_BUFFER
|
|
FILE *pBufferInfo[2] = {NULL, NULL};
|
|
#endif
|
|
|
|
ERRORTYPE _VideoEisCreate(VIDEOEISDATATYPE *pVideoEISData)
|
|
{
|
|
ERRORTYPE eError = SUCCESS;
|
|
int iRet = 0;
|
|
int i = 0;
|
|
|
|
if (pVideoEISData->mEisHd && (EIS_ALGO_MODE_BP != pVideoEISData->mEISAttr.eEisAlgoMode)) {
|
|
alogd("You have already create the EIS handle.");
|
|
return SUCCESS;
|
|
}
|
|
|
|
#ifdef DEBUG_GYRO_BUFFER
|
|
/* create one file to store buffer information */
|
|
char pBufferTmp[4096];
|
|
char *pTmp = &pBufferTmp[0];
|
|
|
|
iRet = sprintf(pTmp, "/mnt/extsd/gyro_buffer_info_%dx%d.txt",
|
|
pVideoEISData->mEISAttr.iVideoInWidth, pVideoEISData->mEISAttr.iVideoInHeight);
|
|
pTmp += iRet; *pTmp++ = '\0';
|
|
|
|
pBufferInfo[pVideoEISData->mMppChnInfo.mChnId] = fopen(pBufferTmp, "w+");
|
|
if (pBufferInfo[pVideoEISData->mMppChnInfo.mChnId] == NULL) {
|
|
aloge("open file /mnt/extsd/gyro_buffer_info[%d].txt failed!!", pVideoEISData->mMppChnInfo.mChnId);
|
|
return eError;
|
|
}
|
|
#endif
|
|
|
|
pVideoEISData->pInputBufMgr = VideoBufMgrCreate(pVideoEISData->mEISAttr.iInputBufNum, 0);
|
|
if (NULL == pVideoEISData->pInputBufMgr) {
|
|
aloge("Create EIS video input buffer manager failed.");
|
|
goto ECrtInput;
|
|
}
|
|
eError = _EisCreateOutputBufPool(pVideoEISData);
|
|
if (SUCCESS != eError) {
|
|
aloge("Create EIS video output buffer pool failed.");
|
|
goto ECrtOutputPool;
|
|
}
|
|
|
|
switch (pVideoEISData->mEISAttr.eEisAlgoMode) {
|
|
case EIS_ALGO_MODE_SW: {
|
|
aloge("You choice the software EIS, but it can't be use now, so use hardware EIS process.");
|
|
}
|
|
case EIS_ALGO_MODE_HW: {
|
|
pVideoEISData->pstEISPkt = malloc(pVideoEISData->mEISAttr.iInputBufNum*sizeof(EISE_FrameData));
|
|
if (NULL == pVideoEISData->pstEISPkt) {
|
|
aloge("Alloc EIS process packet failed, errno %d.", errno);
|
|
goto EAllocPkts;
|
|
}
|
|
|
|
memset(pVideoEISData->pstEISPkt, 0, pVideoEISData->mEISAttr.iInputBufNum*sizeof(EISE_FrameData));
|
|
/* All packets has not be used */
|
|
pVideoEISData->mEisPktMap = 0;
|
|
pVideoEISData->pLastUsedEISPkt = NULL;
|
|
for (i = 0; i < pVideoEISData->mEISAttr.iInputBufNum; i++)
|
|
pVideoEISData->pstEISPkt[i].fid = i; // Not accumulate.
|
|
VideoEisSetHwCfgs(pVideoEISData);
|
|
iRet = EIS_Create(&pVideoEISData->mEisCfg, &pVideoEISData->mEisHd);
|
|
if (iRet < 0) {
|
|
aloge("Create EIS hardware handle failed. ret %d.", iRet);
|
|
eError = ERR_EIS_FAILED_NOTENABLE;
|
|
goto EEisCrt;
|
|
}
|
|
|
|
/* If there has no gyro hardware device, then only use unit matrix. */
|
|
if (!pVideoEISData->bHasGyroDev && !pVideoEISData->mEISAttr.bSimuOffline)
|
|
EIS_Set_UnitMatrix_Flag(&pVideoEISData->mEisHd, 0);
|
|
|
|
// EIS_SetFrq(pVideoEISData->iEisHwFreq, &pVideoEISData->mEisHd);
|
|
} break;
|
|
|
|
case EIS_ALGO_MODE_BP: {
|
|
char pBufferTmp[4096];
|
|
char *pTmp = &pBufferTmp[0];
|
|
static int iBPTestCnt = 0;
|
|
|
|
alogw("You choice the by pass EIS mode, I will output the origin gyro and video buffer with no process.");
|
|
pVideoEISData->bByPassMode = 1;
|
|
pVideoEISData->pBPDataSavePath = pVideoEISData->mEISAttr.pBPDataSavePath;
|
|
iRet = sprintf(pTmp, "%s/EISGyroDataCache%dx%dCnt%d.txt", pVideoEISData->pBPDataSavePath,
|
|
pVideoEISData->mEISAttr.iVideoOutWidth, pVideoEISData->mEISAttr.iVideoOutHeight, iBPTestCnt);
|
|
pTmp += iRet; *pTmp++ = '\0';
|
|
pVideoEISData->pGyroPtsDataFd = fopen(pBufferTmp, "w+");
|
|
|
|
pTmp = &pBufferTmp[0];
|
|
iRet = sprintf(pTmp, "%s/EISVideoPtsCache%dx%dCnt%d.txt", pVideoEISData->pBPDataSavePath,
|
|
pVideoEISData->mEISAttr.iVideoOutWidth, pVideoEISData->mEISAttr.iVideoOutHeight, iBPTestCnt);
|
|
pTmp += iRet; *pTmp++ = '\0';
|
|
pVideoEISData->pVideoPtsFd = fopen(pBufferTmp, "w+");
|
|
|
|
if (pVideoEISData->mEISAttr.bSaveYUV) {
|
|
pTmp = &pBufferTmp[0];
|
|
iRet = sprintf(pTmp, "%s/EISpVideoDataCache%dx%dCnt%d.nv12", pVideoEISData->pBPDataSavePath,
|
|
pVideoEISData->mEISAttr.iVideoOutWidth, pVideoEISData->mEISAttr.iVideoOutHeight, iBPTestCnt);
|
|
pTmp += iRet; *pTmp++ = '\0';
|
|
pVideoEISData->pVideoDataFd = fopen(pBufferTmp, "w+");
|
|
}
|
|
if (!pVideoEISData->pGyroPtsDataFd || !pVideoEISData->pVideoPtsFd
|
|
|| (!pVideoEISData->pVideoDataFd && pVideoEISData->mEISAttr.bSaveYUV)) {
|
|
aloge("Open %s/xxx cache files failed, check if you have enough space or this path.\r\n", pVideoEISData->pBPDataSavePath);
|
|
eError = ERR_EIS_FAILED_NOTENABLE;
|
|
goto EOSaveFd;
|
|
}
|
|
if (pVideoEISData->mEISAttr.iVideoOutWidth == 800 && pVideoEISData->mEISAttr.iVideoOutHeight == 448)
|
|
iBPTestCnt++;
|
|
} break;
|
|
|
|
default: {
|
|
aloge("Wrong EIS algoram mode[%d], return.", pVideoEISData->mEISAttr.eEisAlgoMode);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
} break;
|
|
}
|
|
|
|
return eError;
|
|
|
|
EOSaveFd:
|
|
if (pVideoEISData->pGyroPtsDataFd)
|
|
fclose(pVideoEISData->pGyroPtsDataFd);
|
|
if (pVideoEISData->pVideoPtsFd)
|
|
fclose(pVideoEISData->pVideoPtsFd);
|
|
if (pVideoEISData->pVideoDataFd)
|
|
fclose(pVideoEISData->pVideoDataFd);
|
|
EEisCrt:
|
|
_EisDestroyOutputBufPool(pVideoEISData);
|
|
ECrtOutputPool:
|
|
free(pVideoEISData->pstEISPkt);
|
|
EAllocPkts:
|
|
VideoBufMgrDestroy(pVideoEISData->pInputBufMgr);
|
|
ECrtInput:
|
|
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE _VideoEisDestroy(VIDEOEISDATATYPE *pVideoEISData)
|
|
{
|
|
ERRORTYPE eError = SUCCESS;
|
|
int iRet = 0;
|
|
|
|
if (!pVideoEISData->mEisHd && (EIS_ALGO_MODE_BP != pVideoEISData->mEISAttr.eEisAlgoMode)) {
|
|
alogd("You have already destroy the EIS handle.");
|
|
return SUCCESS;
|
|
}
|
|
|
|
VideoBufMgrWaitUsingEmpty(pVideoEISData->pInputBufMgr);
|
|
_EisDestroyOutputBufPool(pVideoEISData);
|
|
switch (pVideoEISData->mEISAttr.eEisAlgoMode) {
|
|
case EIS_ALGO_MODE_SW: // Until now, there has no real software EIS process mode.
|
|
case EIS_ALGO_MODE_HW: {
|
|
free(pVideoEISData->pstEISPkt);
|
|
VideoBufMgrDestroy(pVideoEISData->pInputBufMgr);
|
|
|
|
iRet = EIS_Destroy(&pVideoEISData->mEisHd);
|
|
if (iRet < 0) {
|
|
aloge("Destroy EIS hardware handle failed. ret %d.", iRet);
|
|
eError = ERR_EIS_FAILED_NOTDISABLE;
|
|
}
|
|
pVideoEISData->mEisHd = NULL;
|
|
} break;
|
|
|
|
case EIS_ALGO_MODE_BP: {
|
|
alogw("You choice the bypass EIS mode, and I save all useful datas.");
|
|
pVideoEISData->bByPassMode = 0;
|
|
pVideoEISData->pBPDataSavePath = NULL;
|
|
if (pVideoEISData->pGyroPtsDataFd)
|
|
fclose(pVideoEISData->pGyroPtsDataFd);
|
|
if (pVideoEISData->pVideoPtsFd)
|
|
fclose(pVideoEISData->pVideoPtsFd);
|
|
if (pVideoEISData->pVideoDataFd)
|
|
fclose(pVideoEISData->pVideoDataFd);
|
|
} break;
|
|
|
|
default: {
|
|
aloge("Wrong EIS algoram mode[%d], return.", pVideoEISData->mEISAttr.eEisAlgoMode);
|
|
eError = ERR_EIS_INVALID_PARA;
|
|
} break;
|
|
}
|
|
|
|
#ifdef DEBUG_GYRO_BUFFER
|
|
fclose(pBufferInfo[pVideoEISData->mMppChnInfo.mChnId]);
|
|
#endif
|
|
|
|
return eError;
|
|
}
|
|
|
|
static void _EisInitAttrs(VIDEOEISDATATYPE* pVideoEISData)
|
|
{
|
|
pVideoEISData->iEisHwFreq = 696;
|
|
pVideoEISData->mEISAttr.iGyroFreq = 1000;
|
|
pVideoEISData->mEISAttr.iGyroPoolSize = 1000 / pVideoEISData->mEISAttr.iGyroFreq * 1000;
|
|
pVideoEISData->mEISAttr.iGyroAxiNum = 3;
|
|
pVideoEISData->mEISAttr.iVideoInWidth = 1920;
|
|
pVideoEISData->mEISAttr.iVideoOutHeight = 1080;
|
|
pVideoEISData->mEISAttr.iVideoInWidthStride = 1920;
|
|
pVideoEISData->mEISAttr.iVideoInHeightStride = 1080;
|
|
pVideoEISData->mEISAttr.iVideoOutWidth = 1920;
|
|
pVideoEISData->mEISAttr.iVideoOutHeight = 1080;
|
|
pVideoEISData->mEISAttr.iVideoFps = 30;
|
|
pVideoEISData->mEISAttr.eVideoFmt = MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
|
|
pVideoEISData->mEISAttr.iInputBufNum = 11;
|
|
pVideoEISData->mEISAttr.iOutputBufBum = 10;
|
|
pVideoEISData->mEISAttr.iEisFilterWidth = 8;
|
|
pVideoEISData->mEISAttr.bRetInFrmFast = 0;
|
|
pVideoEISData->mEISAttr.iDelayTimeMs = 1000/pVideoEISData->mEISAttr.iVideoFps;
|
|
pVideoEISData->mEISAttr.iSyncErrTolerance = 5; /* ms */
|
|
pVideoEISData->mEISAttr.bUseKmat = 0;
|
|
pVideoEISData->mEISAttr.stEisKmat.KmatK1 = 1283.8f;
|
|
pVideoEISData->mEISAttr.stEisKmat.KmatK2 = 1208.2f;
|
|
pVideoEISData->mEISAttr.stEisKmat.KmatKx = 1266.9f;
|
|
pVideoEISData->mEISAttr.stEisKmat.KmatKy = 754.5f;
|
|
|
|
pVideoEISData->mGyroAttr.dev_name = GYRO_DEV_NAME;
|
|
pVideoEISData->mGyroAttr.dev_dir_path = GYRO_DEV_DIR_PATH;
|
|
pVideoEISData->mGyroAttr.kfifo_len = 200;
|
|
pVideoEISData->mGyroAttr.sample_freq = pVideoEISData->mEISAttr.iGyroFreq;
|
|
pVideoEISData->mGyroAttr.axi_num = pVideoEISData->mEISAttr.iGyroAxiNum;
|
|
pVideoEISData->mGyroAttr.force_open = 0;
|
|
pVideoEISData->mGyroAttr.proc_mth = TS_AVERAGE_PROC;
|
|
pVideoEISData->mGyroAttr.rb_len = pVideoEISData->mEISAttr.iGyroPoolSize;
|
|
}
|
|
|
|
ERRORTYPE VideoEISComponentInit(PARAM_IN COMP_HANDLETYPE hComponent)
|
|
{
|
|
int i = 0;
|
|
ERRORTYPE eError = SUCCESS;
|
|
|
|
MM_COMPONENTTYPE *pComp = (MM_COMPONENTTYPE *)hComponent;
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)malloc(sizeof(VIDEOEISDATATYPE));
|
|
|
|
memset(pVideoEISData, 0x0, sizeof(VIDEOEISDATATYPE));
|
|
pComp->pComponentPrivate = (void *)pVideoEISData;
|
|
pVideoEISData->state = COMP_StateLoaded;
|
|
pthread_mutex_init(&pVideoEISData->mStateLock, NULL);
|
|
pthread_mutex_init(&pVideoEISData->mEISLock, NULL);
|
|
pthread_mutex_init(&pVideoEISData->mInputFrmLock, NULL);
|
|
pVideoEISData->hSelf = hComponent;
|
|
|
|
cdx_sem_init(&pVideoEISData->mSemWaitOutFrame, 0);
|
|
/* Fill callback function pointers */
|
|
pComp->SetCallbacks = VideoEISSetCallbacks;
|
|
pComp->SendCommand = VideoEISSendCommand;
|
|
pComp->GetConfig = VideoEISGetConfig;
|
|
pComp->SetConfig = VideoEISSetConfig;
|
|
pComp->GetState = VideoEISGetState;
|
|
pComp->ComponentTunnelRequest = VideoEISComponentTunnelRequest;
|
|
pComp->ComponentDeInit = VideoEISComponentDeInit;
|
|
pComp->EmptyThisBuffer = VideoEISEmptyThisBuffer;
|
|
pComp->FillThisBuffer = VideoEISFillThisBuffer;
|
|
|
|
/* Initialize component data structures to default values */
|
|
pVideoEISData->sPortParam.nPorts = 0;
|
|
pVideoEISData->sPortParam.nStartPortNumber = 0x0;
|
|
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].bEnabled = TRUE;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].eDomain = COMP_PortDomainVideo;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].eDir = COMP_DirInput;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].format.video.cMIMEType = "YVU420";
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].format.video.nFrameWidth = 176;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].format.video.nFrameHeight = 144;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].format.video.eCompressionFormat = PT_BUTT;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_VIDEO_IN].format.video.eColorFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
|
|
pVideoEISData->sPortBufSupplier[EIS_CHN_PORT_INDEX_VIDEO_IN].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortBufSupplier[EIS_CHN_PORT_INDEX_VIDEO_IN].eBufferSupplier = COMP_BufferSupplyOutput;
|
|
pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_VIDEO_IN].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_VIDEO_IN].eTunnelType = TUNNEL_TYPE_COMMON;
|
|
pVideoEISData->sPortParam.nPorts++;
|
|
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].bEnabled = TRUE;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].eDomain = COMP_PortDomainVideo;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].eDir = COMP_DirInput;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].format.video.cMIMEType = "YVU420";
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].format.video.nFrameWidth = 176;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].format.video.nFrameHeight = 144;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].format.video.eCompressionFormat = PT_BUTT; // YCbCr420;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_GYRO_IN].format.video.eColorFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
|
|
pVideoEISData->sPortBufSupplier[EIS_CHN_PORT_INDEX_GYRO_IN].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortBufSupplier[EIS_CHN_PORT_INDEX_GYRO_IN].eBufferSupplier = COMP_BufferSupplyOutput;
|
|
pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_GYRO_IN].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_GYRO_IN].eTunnelType = TUNNEL_TYPE_COMMON;
|
|
pVideoEISData->sPortParam.nPorts++;
|
|
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].bEnabled = TRUE;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].eDomain = COMP_PortDomainVideo;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].eDir = COMP_DirOutput;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].format.video.cMIMEType = "YVU420";
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].format.video.nFrameWidth = 176;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].format.video.nFrameHeight = 144;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].format.video.eCompressionFormat = PT_BUTT; // YCbCr420;
|
|
pVideoEISData->sPortDef[EIS_CHN_PORT_INDEX_OUT].format.video.eColorFormat = MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
|
|
pVideoEISData->sPortBufSupplier[EIS_CHN_PORT_INDEX_OUT].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortBufSupplier[EIS_CHN_PORT_INDEX_OUT].eBufferSupplier = COMP_BufferSupplyOutput;
|
|
pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_OUT].nPortIndex = pVideoEISData->sPortParam.nPorts;
|
|
pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_OUT].eTunnelType = TUNNEL_TYPE_COMMON;
|
|
pVideoEISData->sPortParam.nPorts++;
|
|
|
|
/* EIS attribution initialize */
|
|
_EisInitAttrs(pVideoEISData);
|
|
|
|
if (message_create(&pVideoEISData->cmd_queue) < 0) {
|
|
aloge("message error!");
|
|
eError = ERR_VI_NOMEM;
|
|
goto ECrtMsg;
|
|
}
|
|
|
|
/* Create the component thread to do video stabilization
|
|
* the question is: should we open the gyro after create the gyro thread immediately? no.
|
|
*/
|
|
if (pthread_create(&pVideoEISData->mEISTrd, NULL, EIS_CompStabThread, pVideoEISData)) {
|
|
aloge("create EIS_CompStabThread fail!");
|
|
eError = ERR_VI_NOMEM;
|
|
goto ECrtStab;
|
|
}
|
|
|
|
alogv("VideoEIS component Init success!");
|
|
return SUCCESS;
|
|
|
|
ECrtStab:
|
|
message_destroy(&pVideoEISData->cmd_queue);
|
|
ECrtMsg:
|
|
free(pVideoEISData);
|
|
return eError;
|
|
}
|
|
|
|
ERRORTYPE VideoEISComponentDeInit(PARAM_IN COMP_HANDLETYPE hComponent)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData;
|
|
message_t msg;
|
|
struct list_head *pList;
|
|
ERRORTYPE eError = SUCCESS;
|
|
int cnt = 0;
|
|
|
|
if (NULL == hComponent) {
|
|
aloge("Fatel error: NULL pointer.");
|
|
return ERR_EIS_NOT_PERM;
|
|
}
|
|
|
|
pVideoEISData = (VIDEOEISDATATYPE *)(((MM_COMPONENTTYPE *)hComponent)->pComponentPrivate);
|
|
|
|
CompInternalMsgType eCmd = Stop;
|
|
msg.command = eCmd;
|
|
put_message(&pVideoEISData->cmd_queue, &msg);
|
|
pthread_join(pVideoEISData->mEISTrd, (void *)&eError);
|
|
|
|
message_destroy(&pVideoEISData->cmd_queue);
|
|
|
|
pthread_mutex_destroy(&pVideoEISData->mInputFrmLock);
|
|
pthread_mutex_destroy(&pVideoEISData->mStateLock);
|
|
pthread_mutex_destroy(&pVideoEISData->mEISLock);
|
|
cdx_sem_deinit(&pVideoEISData->mSemWaitOutFrame);
|
|
|
|
free(pVideoEISData);
|
|
pVideoEISData = NULL;
|
|
alogv("VideoEIS component exited!");
|
|
|
|
return eError;
|
|
}
|
|
|
|
void _GyroDebugDumpAllChannelInfos(struct gyro_device_attr *gyro_attr)
|
|
{
|
|
int i = 0;
|
|
|
|
for (i = 0; i < gyro_attr->arry_elems; i++) {
|
|
printf("Channel [%d]:\r\n", i);
|
|
printf("\tName\t%s\r\n", gyro_attr->iio_chn[i].name);
|
|
printf("\tGName\t%s\r\n", gyro_attr->iio_chn[i].generic_name);
|
|
printf("\tScale\t%f\r\n", gyro_attr->iio_chn[i].scale);
|
|
printf("\toffset\t%f\r\n", gyro_attr->iio_chn[i].offset);
|
|
printf("\tindex\t%u\r\n", gyro_attr->iio_chn[i].index);
|
|
printf("\tbytes\t%u\r\n", gyro_attr->iio_chn[i].bytes);
|
|
printf("\tbitused\t%u\r\n", gyro_attr->iio_chn[i].bits_used);
|
|
printf("\tshift\t%u\r\n", gyro_attr->iio_chn[i].shift);
|
|
printf("\tbe\t%u\r\n", gyro_attr->iio_chn[i].be);
|
|
printf("\tis_sign\t%u\r\n", gyro_attr->iio_chn[i].is_signed);
|
|
printf("\tlocation\t%u\r\n\n", gyro_attr->iio_chn[i].location);
|
|
}
|
|
}
|
|
|
|
static void *EIS_CompGyroThread(void *pThreadData)
|
|
{
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)pThreadData;
|
|
|
|
int iGyroReadGrainSize = pVideoEISData->mEISAttr.iGyroFreq/pVideoEISData->mEISAttr.iVideoFps;
|
|
int iGyroReadTimeIntervalUs = (1000/pVideoEISData->mEISAttr.iVideoFps)/2*1000;
|
|
int iRet = 0;
|
|
|
|
message_t cmd_msg;
|
|
|
|
alogv("VideoEIS ComponentGyroThread start run...");
|
|
prctl(PR_SET_NAME, "EIS_CompGyroThread", 0, 0, 0);
|
|
|
|
#if 0
|
|
int ret = 0;
|
|
cpu_set_t stCpuSet;
|
|
memset(&stCpuSet, 0, sizeof(cpu_set_t));
|
|
CPU_ZERO(&stCpuSet);
|
|
CPU_SET(3, &stCpuSet);
|
|
ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &stCpuSet);
|
|
if (ret < 0) {
|
|
aloge("sched_setaffinity failed!!\r\n");
|
|
}
|
|
alogv("sched_setaffinity for GyroHw_CapThread\r\n");
|
|
#endif
|
|
|
|
#if 0
|
|
struct sched_param stSchedPara;
|
|
stSchedPara.sched_priority = 1;
|
|
sched_setscheduler(syscall(__NR_gettid), SCHED_RR, &stSchedPara);
|
|
// sched_setparam(syscall(__NR_gettid), const struct sched_param *param);
|
|
|
|
alogv("loop GyroHw_CapThread, freq:%d, one read sequence gyro number:%d.\r\n",
|
|
pVideoEISData->mEISAttr.iGyroFreq, iGyroReadGrainSize);
|
|
|
|
// _GyroDebugDumpAllChannelInfos(&pVideoEISData->mGyroAttr);
|
|
#endif
|
|
while (pVideoEISData->bGyroRunFlag) {
|
|
#if 0
|
|
fd_set stRdFdSet;
|
|
struct timeval stTimeLimit;
|
|
|
|
FD_ZERO(&stRdFdSet);
|
|
FD_SET(pVideoEISData->mGyroAttr.gyro_fd, &stRdFdSet);
|
|
|
|
stTimeLimit.tv_sec = 2;
|
|
stTimeLimit.tv_usec = 0;
|
|
|
|
iRet = select(pVideoEISData->mGyroAttr.gyro_fd + 1, &stRdFdSet, NULL, NULL, &stTimeLimit);
|
|
if (iRet < 0) {
|
|
aloge("Select wait for gyro datas failed, return %d.", -errno);
|
|
continue;
|
|
} else if (0 == iRet) {
|
|
aloge("Select wait for gyro datas timeout.");
|
|
continue;
|
|
}
|
|
|
|
iRet = _GyroHw_ReadParseRawDatas(pVideoEISData->GryoRingBufHd, &pVideoEISData->mGyroAttr,
|
|
iGyroReadGrainSize, pVideoEISData->mEISAttr.iVideoFps);
|
|
if (iRet == 0) {
|
|
continue;
|
|
}
|
|
#endif
|
|
if (pVideoEISData->bByPassMode && pVideoEISData->state == COMP_StateExecuting) {
|
|
int i = 0;
|
|
char pBufferTmp[4096];
|
|
int iStrLen = 0;
|
|
|
|
for (i = 0; i < iGyroReadGrainSize; i++) {
|
|
EIS_GYRO_PACKET_S stGyroPktOut;
|
|
|
|
if (0 == ring_buffer_out(pVideoEISData->GryoRingBufHd, &stGyroPktOut, 1))
|
|
break;
|
|
|
|
iStrLen = sprintf(&pBufferTmp[0], "%llu %f %f %f\n", stGyroPktOut.dTimeStamp,
|
|
stGyroPktOut.fAnglrVX, stGyroPktOut.fAnglrVY, stGyroPktOut.fAnglrVZ);
|
|
pBufferTmp[iStrLen] = '\0';
|
|
fwrite(&pBufferTmp[0], iStrLen, 1, pVideoEISData->pGyroPtsDataFd);
|
|
}
|
|
}
|
|
|
|
/* Do not read too frequently */
|
|
usleep(iGyroReadTimeIntervalUs/2);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#if 1
|
|
|
|
static inline void _DumpGyroDatas2File
|
|
(VIDEOEISDATATYPE *pVideoEISData, void *pstGyroData, bool bFloatTs)
|
|
{
|
|
#ifdef DEBUG_GYRO_BUFFER
|
|
int iRet = 0;
|
|
char pBufferTmp[4096];
|
|
char *pTmp = &pBufferTmp[0];
|
|
EIS_GYRO_PACKET_S *pstGyroPkt = (EIS_GYRO_PACKET_S *)pstGyroData;
|
|
|
|
if (bFloatTs)
|
|
iRet = sprintf(pTmp, "%lf %f %f %f\n", (double)pstGyroPkt->dTimeStamp/1000000.0f,
|
|
pstGyroPkt->fAnglrVX, pstGyroPkt->fAnglrVY, pstGyroPkt->fAnglrVZ);
|
|
else
|
|
iRet = sprintf(pTmp, "%llu %f %f %f\n", pstGyroPkt->dTimeStamp,
|
|
pstGyroPkt->fAnglrVX, pstGyroPkt->fAnglrVY, pstGyroPkt->fAnglrVZ);
|
|
|
|
fwrite(&pBufferTmp[0], 1, iRet, pBufferInfo[pVideoEISData->mMppChnInfo.mChnId]);
|
|
pTmp = &pBufferTmp[0];
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Tsv Tsv
|
|
* Texp / /
|
|
* *---------* *---------*
|
|
* |*---------* *---------*
|
|
* | *---------* *---------*
|
|
* | *---------* *---------*
|
|
* | |
|
|
* Pn(pack gyro data number, equal to [iVideoLineTime])
|
|
*/
|
|
static EISE_FrameData* _SyncAndPacketEisHardwareBuffer
|
|
(VIDEOEISDATATYPE *pVideoEISData, VIDEO_FRAME_S *pstVFrm)
|
|
{
|
|
int i = 0;
|
|
int iCurPktIdx = 0;
|
|
EISE_FrameData *pstEISFrmTmp = NULL;
|
|
struct ring_buffer* pGyroRBHd = pVideoEISData->GryoRingBufHd;
|
|
|
|
#if 1
|
|
/* We must can find one, do not worry it will be failure. */
|
|
for (i = 0; i < pVideoEISData->mEISAttr.iInputBufNum; i++) {
|
|
if (!(pVideoEISData->mEisPktMap & (1 << i))) {
|
|
pstEISFrmTmp = &pVideoEISData->pstEISPkt[i];
|
|
pVideoEISData->mEisPktMap |= (1 << i);
|
|
iCurPktIdx = i;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
int iRet = 0;
|
|
unsigned int iAbsOfGyroAndVideoTs = 0; /* Unit: ms */
|
|
EIS_GYRO_PACKET_S stGyroPkt;
|
|
/* Use delay time to fix video data's timestamp. */
|
|
uint64_t dFixedVideoPts = 0; /* Unit: us */
|
|
uint64_t dVideoFrameIntervalMs = 1000/pVideoEISData->mEISAttr.iVideoFps; /* Unit: ms */
|
|
uint64_t dPacktEndTimeStamp = 0, dPacktStartTimeStamp = 0; /* Unit: us */
|
|
uint64_t dGyroIntervalUs = 1000000/pVideoEISData->mGyroAttr.sample_freq;
|
|
uint64_t dGyroDataExtendIntervalUs = 0;
|
|
int iNeedGyroDataNum = pVideoEISData->mGyroAttr.sample_freq/pVideoEISData->mEISAttr.iVideoFps;
|
|
int iFixedDelayTime = 0;
|
|
|
|
if (pstVFrm->mExposureTime > dVideoFrameIntervalMs)
|
|
pstVFrm->mExposureTime = dVideoFrameIntervalMs;
|
|
|
|
/* We use the half of exposure time te be the end of packet node. */
|
|
iFixedDelayTime = pVideoEISData->mEISAttr.iDelayTimeMs + pstVFrm->mExposureTime/2;
|
|
|
|
dFixedVideoPts = (iFixedDelayTime > 0)
|
|
? pstVFrm->mpts - iFixedDelayTime*1000
|
|
: pstVFrm->mpts + abs(iFixedDelayTime)*1000;
|
|
|
|
// printf("EIS:[%u]\n", pstVFrm->mExposureTime);
|
|
dPacktEndTimeStamp = dFixedVideoPts - dVideoFrameIntervalMs*1000
|
|
+ (uint64_t)(pVideoEISData->mEisCfg.td*1000000.0f);
|
|
|
|
dPacktStartTimeStamp = dPacktEndTimeStamp - dVideoFrameIntervalMs*1000;
|
|
|
|
#ifdef DEBUG_GYRO_BUFFER
|
|
char pBufferTmp[4096];
|
|
char *pTmp = &pBufferTmp[0];
|
|
|
|
iRet = sprintf(pTmp, "Get one video pst[%lld], fixed[%lld], exp_time %u",
|
|
pstVFrm->mpts, dPacktStartTimeStamp, pstVFrm->mExposureTime);
|
|
pTmp += iRet;
|
|
*pTmp++ = '\n';
|
|
fwrite(&pBufferTmp[0], 1, (pTmp-&pBufferTmp[0]), pBufferInfo[pVideoEISData->mMppChnInfo.mChnId]);
|
|
pTmp = &pBufferTmp[0];
|
|
#endif
|
|
|
|
i = 0;
|
|
while (1) {
|
|
/* First of all, we will past the all old gyro data packets,
|
|
* find the nextest start one gyro data with timestamp.
|
|
*/
|
|
if (ring_buffer_out(pGyroRBHd, &stGyroPkt, 1) <= 0)
|
|
goto EEmptyRB;
|
|
|
|
_DumpGyroDatas2File(pVideoEISData, &stGyroPkt, 1);
|
|
|
|
/* The oldest gyro data value is too fresh,
|
|
* even it is low probability, but we still catch it. */
|
|
if (stGyroPkt.dTimeStamp >= dPacktEndTimeStamp)
|
|
goto EEmptyRB;
|
|
|
|
iAbsOfGyroAndVideoTs = llabs(dPacktStartTimeStamp - stGyroPkt.dTimeStamp);
|
|
if (iAbsOfGyroAndVideoTs <= pVideoEISData->mEISAttr.iSyncErrTolerance*1000
|
|
|| stGyroPkt.dTimeStamp >= dPacktStartTimeStamp) {
|
|
pstEISFrmTmp->gyro_data[i].time = stGyroPkt.dTimeStamp;
|
|
pstEISFrmTmp->gyro_data[i].ax = stGyroPkt.fAccelVX*pVideoEISData->mEisPrivAttr.fGyroAxScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].ay = stGyroPkt.fAccelVY*pVideoEISData->mEisPrivAttr.fGyroAyScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].az = stGyroPkt.fAccelVZ*pVideoEISData->mEisPrivAttr.fGyroAzScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vx = stGyroPkt.fAnglrVX*pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vy = stGyroPkt.fAnglrVY*pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vz = stGyroPkt.fAnglrVZ*pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor;
|
|
|
|
_DumpGyroDatas2File(pVideoEISData, &stGyroPkt, 0);
|
|
|
|
pstEISFrmTmp->gyro_data[i].vx -= pVideoEISData->mEisCfg.stable_anglev[0]*pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vy -= pVideoEISData->mEisCfg.stable_anglev[1]*pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vz -= pVideoEISData->mEisCfg.stable_anglev[2]*pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor;
|
|
break;
|
|
}
|
|
}
|
|
i++;
|
|
|
|
while (1) {
|
|
/* If we got one gyro packet success,
|
|
* then use it whatever, even it may not too valid. */
|
|
if (ring_buffer_out(pGyroRBHd, &stGyroPkt, 1) <= 0) {
|
|
aloge("Empty.");
|
|
goto EEmptyRB;
|
|
}
|
|
|
|
pstEISFrmTmp->gyro_data[i].time = stGyroPkt.dTimeStamp;
|
|
pstEISFrmTmp->gyro_data[i].ax = stGyroPkt.fAccelVX*pVideoEISData->mEisPrivAttr.fGyroAxScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].ay = stGyroPkt.fAccelVY*pVideoEISData->mEisPrivAttr.fGyroAyScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].az = stGyroPkt.fAccelVZ*pVideoEISData->mEisPrivAttr.fGyroAzScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vx = stGyroPkt.fAnglrVX*pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vy = stGyroPkt.fAnglrVY*pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vz = stGyroPkt.fAnglrVZ*pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor;
|
|
|
|
_DumpGyroDatas2File(pVideoEISData, &stGyroPkt, 0);
|
|
|
|
pstEISFrmTmp->gyro_data[i].vx -= pVideoEISData->mEisCfg.stable_anglev[0]*pVideoEISData->mEisPrivAttr.fGyroVxScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vy -= pVideoEISData->mEisCfg.stable_anglev[1]*pVideoEISData->mEisPrivAttr.fGyroVyScaleFactor;
|
|
pstEISFrmTmp->gyro_data[i].vz -= pVideoEISData->mEisCfg.stable_anglev[2]*pVideoEISData->mEisPrivAttr.fGyroVzScaleFactor;
|
|
i++;
|
|
|
|
/* Keep one newest timestamp for the next sync */
|
|
if (dPacktEndTimeStamp < stGyroPkt.dTimeStamp
|
|
|| (i >= sizeof(pstEISFrmTmp->gyro_data)/sizeof(pstEISFrmTmp->gyro_data[0])))
|
|
break; // We got enough datas
|
|
}
|
|
|
|
EEmptyRB:
|
|
pVideoEISData->iGVSyncPktId++;
|
|
if (i == 0) {
|
|
if (NULL == pVideoEISData->pLastUsedEISPkt) {
|
|
/* This mean we got an empty buffer packets, construct it. */
|
|
aloge("Got zero gyro buffer datas. video pts[%llu], construct it.", pstVFrm->mpts);
|
|
memset(&pstEISFrmTmp->gyro_data[0], 0, sizeof(pstEISFrmTmp->gyro_data));
|
|
|
|
pstEISFrmTmp->gyro_data[0].time = dPacktStartTimeStamp;
|
|
|
|
dGyroDataExtendIntervalUs = (dPacktEndTimeStamp - dPacktStartTimeStamp)/(iNeedGyroDataNum-1);
|
|
pstEISFrmTmp->gyro_data[0].ax = 0.0f;
|
|
pstEISFrmTmp->gyro_data[0].ay = 0.0f;
|
|
pstEISFrmTmp->gyro_data[0].az = 0.0f;
|
|
pstEISFrmTmp->gyro_data[0].vx = 0.0f;//-0.005f;
|
|
pstEISFrmTmp->gyro_data[0].vy = 0.0f;//-0.002f;
|
|
pstEISFrmTmp->gyro_data[0].vz = 0.0f;//0.004f;
|
|
|
|
_DumpGyroDatas2File(pVideoEISData, &pstEISFrmTmp->gyro_data[0], 0);
|
|
|
|
while (1) {
|
|
i++;
|
|
pstEISFrmTmp->gyro_data[i].time = pstEISFrmTmp->gyro_data[i-1].time + dGyroDataExtendIntervalUs;
|
|
pstEISFrmTmp->gyro_data[i].ax = 0;
|
|
pstEISFrmTmp->gyro_data[i].ay = 0;
|
|
pstEISFrmTmp->gyro_data[i].az = 0;
|
|
pstEISFrmTmp->gyro_data[i].vx = 0.0f;//-0.005f;
|
|
pstEISFrmTmp->gyro_data[i].vy = 0.0f;//-0.002f;
|
|
pstEISFrmTmp->gyro_data[i].vz = 0.0f;//0.004f;
|
|
_DumpGyroDatas2File(pVideoEISData, &pstEISFrmTmp->gyro_data[i], 0);
|
|
if (pstEISFrmTmp->gyro_data[i].time > dPacktEndTimeStamp)
|
|
break;
|
|
}
|
|
} else {
|
|
if (pVideoEISData->bHasGyroDev && pVideoEISData->iGVSyncPktId % pVideoEISData->mEISAttr.iVideoFps == 0)
|
|
/* This mean we got an empty buffer packets. then use the last gyro data one */
|
|
aloge("Got zero gyro buffer datas. video pts[%llu], last pts[%llu], ring buffer kepp[%d].",
|
|
pstVFrm->mpts,
|
|
pVideoEISData->pLastUsedEISPkt->gyro_data[pVideoEISData->pLastUsedEISPkt->gyro_num-1].time,
|
|
ring_buffer_g_validnum(pGyroRBHd));
|
|
|
|
/* Copy all old gyro buffers, and change its timestamps */
|
|
memcpy(&pstEISFrmTmp->gyro_data[0],
|
|
&pVideoEISData->pLastUsedEISPkt->gyro_data[0], sizeof(pstEISFrmTmp->gyro_data));
|
|
|
|
pstEISFrmTmp->gyro_num = pVideoEISData->pLastUsedEISPkt->gyro_num;
|
|
|
|
pstEISFrmTmp->gyro_data[0].time = dPacktStartTimeStamp;
|
|
dGyroDataExtendIntervalUs = (dPacktEndTimeStamp - dPacktStartTimeStamp)/(pstEISFrmTmp->gyro_num-1);
|
|
|
|
if (pVideoEISData->bHasGyroDev && pVideoEISData->iGVSyncPktId % pVideoEISData->mEISAttr.iVideoFps == 0)
|
|
aloge("Got zero gyro buffer datas. video pts0[%llu], num[%d].",
|
|
pstEISFrmTmp->gyro_data[0].time, pstEISFrmTmp->gyro_num);
|
|
|
|
/* Fix timestamps */
|
|
while (1) {
|
|
i++;
|
|
pstEISFrmTmp->gyro_data[i].time = pstEISFrmTmp->gyro_data[i-1].time + dGyroDataExtendIntervalUs;
|
|
if (pstEISFrmTmp->gyro_data[i].time > dPacktEndTimeStamp)
|
|
break;
|
|
}
|
|
}
|
|
} else if (i < iNeedGyroDataNum/4) {
|
|
// TODO:
|
|
/* Too less packets, shoudle we use the last one? */
|
|
/* Should copy the last gyro data to pad the gyro data number, but increase timestamp */
|
|
/* Just keep the exist program, if can not support, then change it. */
|
|
aloge("Too less gyro buffer datas %d, ring buffer keep[%d], then extend to %d datas.\n",
|
|
i, ring_buffer_g_validnum(pGyroRBHd), iNeedGyroDataNum);
|
|
#if 0
|
|
dGyroDataExtendIntervalUs = (dPacktEndTimeStamp - pstEISFrmTmp->gyro_data[i-1].time)/(iNeedGyroDataNum-i);
|
|
for (; i < iNeedGyroDataNum; i++) {
|
|
pstEISFrmTmp->gyro_data[i].time = pstEISFrmTmp->gyro_data[i-1].time + dGyroDataExtendIntervalUs;
|
|
pstEISFrmTmp->gyro_data[i].ax = pstEISFrmTmp->gyro_data[i-1].ax;
|
|
pstEISFrmTmp->gyro_data[i].ay = pstEISFrmTmp->gyro_data[i-1].ay;
|
|
pstEISFrmTmp->gyro_data[i].az = pstEISFrmTmp->gyro_data[i-1].az;
|
|
pstEISFrmTmp->gyro_data[i].vx = pstEISFrmTmp->gyro_data[i-1].vx;
|
|
pstEISFrmTmp->gyro_data[i].vy = pstEISFrmTmp->gyro_data[i-1].vy;
|
|
pstEISFrmTmp->gyro_data[i].vz = pstEISFrmTmp->gyro_data[i-1].vz;
|
|
}
|
|
#endif
|
|
}
|
|
pVideoEISData->pLastUsedEISPkt = pstEISFrmTmp;
|
|
pVideoEISData->dLastInputFrmPts = dPacktEndTimeStamp;
|
|
|
|
pstEISFrmTmp->frame_stamp = dPacktEndTimeStamp;
|
|
pstEISFrmTmp->gyro_num = i;
|
|
#ifdef DEBUG_GYRO_BUFFER
|
|
iRet = sprintf(pTmp, "We got video timestamp[%llu], gyro_num[%d]", pstEISFrmTmp->frame_stamp, i);
|
|
pTmp += iRet;
|
|
*pTmp++ = '\n';
|
|
fwrite(&pBufferTmp[0], 1, (pTmp-&pBufferTmp[0]), pBufferInfo[pVideoEISData->mMppChnInfo.mChnId]);
|
|
pTmp = &pBufferTmp[0];
|
|
|
|
if (i < iNeedGyroDataNum/2 || i > iNeedGyroDataNum*3/2) {
|
|
iRet = sprintf(pTmp, "Toooooooo small or long data num[%d]", i);
|
|
pTmp += iRet;
|
|
*pTmp++ = '\n';
|
|
fwrite(&pBufferTmp[0], 1, (pTmp-&pBufferTmp[0]), pBufferInfo[pVideoEISData->mMppChnInfo.mChnId]);
|
|
pTmp = &pBufferTmp[0];
|
|
}
|
|
#endif
|
|
|
|
return pstEISFrmTmp;
|
|
}
|
|
#endif
|
|
static void *EIS_CompStabThread(void *pThreadData)
|
|
{
|
|
unsigned int cmddata;
|
|
CompInternalMsgType cmd;
|
|
VIDEOEISDATATYPE *pVideoEISData = (VIDEOEISDATATYPE *)pThreadData;
|
|
COMP_INTERNAL_TUNNELINFOTYPE *pOutputPort = &pVideoEISData->sPortTunnelInfo[EIS_CHN_PORT_INDEX_OUT];
|
|
message_t cmd_msg;
|
|
ERRORTYPE eError = 0;
|
|
int iRet = 0;
|
|
|
|
#if 1
|
|
if (pVideoEISData->mEISAttr.eOperationMode != EIS_OPR_VGA30 && pVideoEISData->mEISAttr.eOperationMode != EIS_OPR_VGA60) {
|
|
struct sched_param stSchedPara;
|
|
stSchedPara.sched_priority = 20;
|
|
if (pthread_setschedparam(pthread_self(), SCHED_RR, &stSchedPara))
|
|
aloge("Set EIS_CompStabThread into SCHED_RR failed, %s.", strerror(errno));
|
|
}
|
|
#endif
|
|
|
|
alogv("VideoEIS ComponentStabThread start run...");
|
|
prctl(PR_SET_NAME, "EIS_CompStabThread", 0, 0, 0);
|
|
|
|
while (1) {
|
|
PROCESS_MESSAGE:
|
|
if (get_message(&pVideoEISData->cmd_queue, &cmd_msg) == 0) {
|
|
cmd = cmd_msg.command;
|
|
cmddata = (unsigned int)cmd_msg.para0;
|
|
// alogv("VideoVi ComponentThread get_message cmd:%d", cmd);
|
|
if (cmd == SetState) {
|
|
pthread_mutex_lock(&pVideoEISData->mStateLock);
|
|
if (pVideoEISData->state == (COMP_STATETYPE)(cmddata)) {
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData, COMP_EventError,
|
|
ERR_VI_SAMESTATE, 0, NULL);
|
|
} else {
|
|
switch ((COMP_STATETYPE)(cmddata)) {
|
|
case COMP_StateInvalid: {
|
|
pVideoEISData->state = COMP_StateInvalid;
|
|
// CompSendEvent(pVideoEISData->hSelf, pVideoEISData->pAppData, COMP_EventError, ERR_VI_INVALIDSTATE, 0);
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventError, ERR_VI_INVALIDSTATE, 0, NULL);
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventCmdComplete, COMP_CommandStateSet,
|
|
pVideoEISData->state, NULL);
|
|
} break;
|
|
case COMP_StateLoaded: {
|
|
if (pVideoEISData->state != COMP_StateIdle) {
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventError,
|
|
ERR_VI_INCORRECT_STATE_TRANSITION, 0, NULL);
|
|
}
|
|
pVideoEISData->mWaitAllFrameReleaseFlag = 1;
|
|
|
|
DoVideoEisReturnBackAllInputFrames(pVideoEISData);
|
|
|
|
if (!list_empty(&pVideoEISData->mOutUsedList)) {
|
|
aloge("Wait EIS component output buffer used frame list empty.");
|
|
while (!list_empty(&pVideoEISData->mOutUsedList)) {usleep(10*1000);};
|
|
}
|
|
VideoBufMgrWaitUsingEmpty(pVideoEISData->pInputBufMgr);
|
|
alogd("Wait all EIS component output using frame return done.");
|
|
|
|
pVideoEISData->mWaitAllFrameReleaseFlag = 0;
|
|
pVideoEISData->state = COMP_StateLoaded;
|
|
_VideoEisDestroy(pVideoEISData);
|
|
alogv("Set EIS OMX_StateLoaded OK");
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventCmdComplete, COMP_CommandStateSet,
|
|
pVideoEISData->state, NULL);
|
|
} break;
|
|
case COMP_StateIdle: {
|
|
if (pVideoEISData->state == COMP_StateLoaded) {
|
|
alogv("video VI: loaded->idle ...");
|
|
pVideoEISData->state = COMP_StateIdle;
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf,
|
|
pVideoEISData->pAppData,
|
|
COMP_EventCmdComplete,
|
|
COMP_CommandStateSet,
|
|
pVideoEISData->state, NULL);
|
|
} else if (pVideoEISData->state == COMP_StatePause ||
|
|
pVideoEISData->state == COMP_StateExecuting) {
|
|
alogv("video vi: pause/executing[0x%x]->idle ...", pVideoEISData->state);
|
|
//release all frames to video input.
|
|
if(!VideoBufMgrUsingEmpty(pVideoEISData->pInputBufMgr)) {
|
|
alogw("Fatal warning! using frame is not empty! check code!");
|
|
}
|
|
|
|
pVideoEISData->state = COMP_StateIdle;
|
|
alogv("Set EIS COMP_StateIdle OK");
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventCmdComplete, COMP_CommandStateSet,
|
|
pVideoEISData->state, NULL);
|
|
} else {
|
|
aloge("Fatal error! current state[0x%x] can't turn to idle!", pVideoEISData->state);
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventError,
|
|
ERR_VI_INCORRECT_STATE_TRANSITION, 0, NULL);
|
|
}
|
|
} break;
|
|
case COMP_StateExecuting: { // Transition can only happen from pause or idle state
|
|
if (pVideoEISData->state == COMP_StateIdle || pVideoEISData->state == COMP_StatePause) {
|
|
eError = _VideoEisCreate(pVideoEISData);
|
|
if (SUCCESS != eError) {
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf,
|
|
pVideoEISData->pAppData,
|
|
COMP_EventError,
|
|
COMP_CommandStateSet,
|
|
eError, NULL);
|
|
aloge("Convert status Idle->Executing failed because open hw EIS failed. ret 0x%x.", eError);
|
|
} else {
|
|
pVideoEISData->state = COMP_StateExecuting;
|
|
alogv("Set Virvi COMP_StateExecuting OK");
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf,
|
|
pVideoEISData->pAppData,
|
|
COMP_EventCmdComplete,
|
|
COMP_CommandStateSet,
|
|
pVideoEISData->state, NULL);
|
|
}
|
|
} else {
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventError,
|
|
ERR_VI_INCORRECT_STATE_TRANSITION, 0, NULL);
|
|
}
|
|
} break;
|
|
case COMP_StatePause: {
|
|
/* Transition can only happen from idle or executing state */
|
|
if (pVideoEISData->state == COMP_StateIdle || pVideoEISData->state == COMP_StateExecuting) {
|
|
pVideoEISData->state = COMP_StatePause;
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventCmdComplete, COMP_CommandStateSet,
|
|
pVideoEISData->state, NULL);
|
|
} else {
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventError,
|
|
ERR_VI_INCORRECT_STATE_TRANSITION, 0, NULL);
|
|
}
|
|
} break;
|
|
default: break;
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&pVideoEISData->mStateLock);
|
|
} else if (cmd == Flush) {
|
|
pVideoEISData->pCallbacks->EventHandler(pVideoEISData->hSelf, pVideoEISData->pAppData,
|
|
COMP_EventCmdComplete, COMP_CommandFlush,
|
|
0, NULL);
|
|
} else if (cmd == Stop) {
|
|
/* Kill thread */
|
|
goto EXIT;
|
|
} else if(cmd == EisComp_InputFrameAvailable) {
|
|
alogv("(f:%s, l:%d) frame input", __FUNCTION__, __LINE__);
|
|
} else if(cmd == EisComp_StoreFrame) {
|
|
pVideoEISData->bStoreFrame = TRUE;
|
|
snprintf(pVideoEISData->mDbgStoreFrameFilePath, sizeof(pVideoEISData->mDbgStoreFrameFilePath), "%s", (char*)cmd_msg.mpData);
|
|
/* mpData is malloced in TMessageDeepCopyMessage() */
|
|
free(cmd_msg.mpData);
|
|
cmd_msg.mpData = NULL;
|
|
cmd_msg.mDataSize = 0;
|
|
}
|
|
//precede to process message
|
|
goto PROCESS_MESSAGE;
|
|
}
|
|
|
|
int eError;
|
|
if (pVideoEISData->state == COMP_StateExecuting) {
|
|
int iInputFrmId = 0;
|
|
|
|
/* Find one input buffer from input buffer list, do gyro sync
|
|
* and fetch one output buffer from output buffer list.
|
|
*/
|
|
|
|
/* Get one video buffer and do one sync operation. check if sync successful.
|
|
* 1.if there has no gyro data can be synced, then use the last one.
|
|
*/
|
|
VIDEO_FRAME_INFO_S *pVInFrm;
|
|
pVInFrm = VideoBufMgrGetValidFrame(pVideoEISData->pInputBufMgr);
|
|
if (NULL == pVInFrm) {
|
|
/* Maybe this thread was cut out, and [VideoBufMgrPushFrame] was invoked,
|
|
* but the [pVideoEISData->bWaitingInputFrmFlag] was not set,
|
|
* then this thread will be get into stall. so after set [bWaitingInputFrmFlag],
|
|
* check if we haven't got valid buffer yet, if not, then just sleep, do not worry it will be stall. */
|
|
pVideoEISData->bWaitingInputFrmFlag = TRUE;
|
|
pVInFrm = VideoBufMgrGetValidFrame(pVideoEISData->pInputBufMgr);
|
|
if (NULL == pVInFrm) {
|
|
TMessage_WaitQueueNotEmpty(&pVideoEISData->cmd_queue, 0);
|
|
pVideoEISData->bWaitingInputFrmFlag = FALSE;
|
|
goto PROCESS_MESSAGE;
|
|
} else
|
|
pVideoEISData->bWaitingInputFrmFlag = FALSE;
|
|
}
|
|
|
|
VIDEO_FRAME_INFO_S *pVideoInBufTmp = NULL;
|
|
VIDEO_FRAME_INFO_S stVideoInBufRetTmp;
|
|
/* If is bypass mode, then save all datas in specific path. */
|
|
if (pVideoEISData->bByPassMode) {
|
|
static uint64_t dCacheFrmCnt = 0;
|
|
|
|
EIS_GYRO_PACKET_S stGyroPkt;
|
|
char pBufferTmp[4096];
|
|
int iStrLen = 0;
|
|
pVideoInBufTmp = VideoBufMgrGetSpecUsingFrameWithAddr(
|
|
pVideoEISData->pInputBufMgr, pVInFrm->VFrame.mpVirAddr[0]);
|
|
if (pVideoInBufTmp) {
|
|
pVideoEISData->iCacheBufferNum++;
|
|
iStrLen = sprintf(&pBufferTmp[0], "%llu %u %d\n", pVideoInBufTmp->VFrame.mpts,
|
|
pVideoInBufTmp->VFrame.mExposureTime, pVideoEISData->iCacheBufferNum);
|
|
pBufferTmp[iStrLen] = '\0';
|
|
fwrite(&pBufferTmp[0], iStrLen, 1, pVideoEISData->pVideoPtsFd);
|
|
|
|
if (pVideoEISData->mEISAttr.bSaveYUV) {
|
|
fwrite(pVideoInBufTmp->VFrame.mpVirAddr[0],
|
|
pVideoInBufTmp->VFrame.mHeight*pVideoInBufTmp->VFrame.mWidth, 1, pVideoEISData->pVideoDataFd);
|
|
fwrite(pVideoInBufTmp->VFrame.mpVirAddr[1],
|
|
pVideoInBufTmp->VFrame.mHeight*pVideoInBufTmp->VFrame.mWidth/2, 1, pVideoEISData->pVideoDataFd);
|
|
} else {
|
|
VideoFrameListInfo *pVFrmOutputCur;
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
pVFrmOutputCur = list_first_entry(&pVideoEISData->mOutIdleList, VideoFrameListInfo, mList);
|
|
ion_flushCache(pVideoInBufTmp->VFrame.mpVirAddr[0],
|
|
pVFrmOutputCur->mFrame.VFrame.mWidth*pVFrmOutputCur->mFrame.VFrame.mHeight);
|
|
ion_flushCache(pVideoInBufTmp->VFrame.mpVirAddr[1],
|
|
pVFrmOutputCur->mFrame.VFrame.mWidth*pVFrmOutputCur->mFrame.VFrame.mHeight/2);
|
|
/* If we only have one output idle video frame, then keep it. */
|
|
if (pVideoEISData->iOutFrmIdleCnt > 1) {
|
|
list_move_tail(&pVFrmOutputCur->mList, &pVideoEISData->mOutValidList);
|
|
pVideoEISData->iOutFrmIdleCnt--;
|
|
} else
|
|
aloge("We has only one idle frame in EIS output frame list.");
|
|
pVFrmOutputCur->mFrame.VFrame.mPhyAddr[0] = pVideoInBufTmp->VFrame.mPhyAddr[0];
|
|
pVFrmOutputCur->mFrame.VFrame.mPhyAddr[1] = pVideoInBufTmp->VFrame.mPhyAddr[1];
|
|
pVFrmOutputCur->mFrame.VFrame.mpts = pVideoInBufTmp->VFrame.mpts;
|
|
pVFrmOutputCur->mFrame.VFrame.mExposureTime = pVideoInBufTmp->VFrame.mExposureTime;
|
|
#if 1
|
|
#define POINT_BEGINX 100
|
|
#define POINT_BEGINY 50
|
|
#define POINT_SIZE 3
|
|
#define POINT_LINE_LEN 40
|
|
#define POINT_GRP_SIZE 5
|
|
{
|
|
int i = 0, j = 0, k = 0;
|
|
char *pDrawPosBegin = (char *)pVideoInBufTmp->VFrame.mpVirAddr[0]
|
|
+ pVideoInBufTmp->VFrame.mWidth*POINT_BEGINY+POINT_BEGINX;
|
|
char *pDrawPos = NULL;
|
|
for (i = 0; i < pVideoEISData->iCacheBufferNum; i++) {
|
|
pDrawPos = pDrawPosBegin
|
|
+ (i/POINT_LINE_LEN)*POINT_SIZE*2*pVideoInBufTmp->VFrame.mWidth
|
|
+ (i%POINT_LINE_LEN)*POINT_SIZE*2
|
|
+ (i%POINT_LINE_LEN/POINT_GRP_SIZE*POINT_SIZE);
|
|
|
|
for (j = 0; j < POINT_SIZE; j++) {
|
|
for (k = 0; k < POINT_SIZE; k++) {
|
|
pDrawPos[j*pVideoInBufTmp->VFrame.mWidth+k] = ~pDrawPos[j*pVideoInBufTmp->VFrame.mWidth+k];
|
|
}
|
|
}
|
|
}
|
|
ion_flushCache(pVideoInBufTmp->VFrame.mpVirAddr[0],
|
|
pVFrmOutputCur->mFrame.VFrame.mWidth*pVFrmOutputCur->mFrame.VFrame.mHeight);
|
|
ion_flushCache(pVideoInBufTmp->VFrame.mpVirAddr[1],
|
|
pVFrmOutputCur->mFrame.VFrame.mWidth*pVFrmOutputCur->mFrame.VFrame.mHeight/2);
|
|
}
|
|
#endif
|
|
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
if (pVideoEISData->bWaitingOutFrmFlag && pVideoEISData->iOutFrmIdleCnt >= 1)
|
|
cdx_sem_up(&pVideoEISData->mSemWaitOutFrame);
|
|
}
|
|
|
|
/* Return input buffer to last component, must invoke [DoVideoEisSendBackInputFrame] first */
|
|
stVideoInBufRetTmp = *pVideoInBufTmp;
|
|
VideoBufMgrReleaseFrame(pVideoEISData->pInputBufMgr, pVideoInBufTmp);
|
|
DoVideoEisSendBackInputFrame(pVideoEISData, &stVideoInBufRetTmp);
|
|
}
|
|
goto PROCESS_MESSAGE;
|
|
}
|
|
|
|
VideoFrameListInfo *pVFrmOutputCur;
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
pVFrmOutputCur = list_first_entry(&pVideoEISData->mOutIdleList, VideoFrameListInfo, mList);
|
|
// ion_flushCache(pVFrmOutputCur->mFrame.VFrame.mpVirAddr[0],
|
|
// pVFrmOutputCur->mFrame.VFrame.mWidth*pVFrmOutputCur->mFrame.VFrame.mHeight);
|
|
// ion_flushCache(pVFrmOutputCur->mFrame.VFrame.mpVirAddr[1],
|
|
// pVFrmOutputCur->mFrame.VFrame.mWidth*pVFrmOutputCur->mFrame.VFrame.mHeight/2);
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
|
|
/* Set the next output address. */
|
|
EIS_PROCOUT_PARA stOutputPara;
|
|
memset(&stOutputPara, 0, sizeof(EIS_PROCOUT_PARA));
|
|
stOutputPara.out_luma_mmu_Addr = pVFrmOutputCur->mFrame.VFrame.mpVirAddr[0];
|
|
stOutputPara.out_luma_phy_Addr = pVFrmOutputCur->mFrame.VFrame.mPhyAddr[0];
|
|
stOutputPara.out_chroma_u_mmu_Addr = pVFrmOutputCur->mFrame.VFrame.mpVirAddr[1];
|
|
stOutputPara.out_chroma_u_phy_Addr = pVFrmOutputCur->mFrame.VFrame.mPhyAddr[1];
|
|
EIS_setOutputAddr(&pVideoEISData->mEisHd, &stOutputPara);
|
|
|
|
EISE_FrameData* pEisProcPkt;
|
|
int iEisProcRet = 0;
|
|
|
|
pEisProcPkt = _SyncAndPacketEisHardwareBuffer(pVideoEISData, &pVInFrm->VFrame);
|
|
// pEisProcPkt->frame_stamp = pVInFrm->VFrame.mpts;
|
|
pEisProcPkt->texp = (float)pVInFrm->VFrame.mExposureTime/1000.0f;
|
|
// aloge("Send video pts: %f %f gyro_num[%d] %f %f %f %f to process.",
|
|
// pEisProcPkt->frame_stamp, pEisProcPkt->texp, pEisProcPkt->gyro_num, pEisProcPkt->gyro_data[0].time,
|
|
// pEisProcPkt->gyro_data[0].vx, pEisProcPkt->gyro_data[0].vy, pEisProcPkt->gyro_data[0].vz);
|
|
pEisProcPkt->in_addr.in_luma_mmu_Addr = pVInFrm->VFrame.mpVirAddr[0];
|
|
pEisProcPkt->in_addr.in_luma_phy_Addr = pVInFrm->VFrame.mPhyAddr[0];
|
|
pEisProcPkt->in_addr.in_chroma_mmu_Addr = pVInFrm->VFrame.mpVirAddr[1];
|
|
pEisProcPkt->in_addr.in_chroma_phy_Addr = pVInFrm->VFrame.mPhyAddr[1];
|
|
#if 0
|
|
static unsigned long long iSelfProcTest = 0;
|
|
if (iSelfProcTest >= pVideoEISData->mEISAttr.iInputBufNum-3) {
|
|
iGetFrmId = iSelfProcTest % (pVideoEISData->mEISAttr.iInputBufNum-3);
|
|
iEisProcRet = LIB_S_OK;
|
|
} else {
|
|
iEisProcRet = LIB_E_BUFFER_NOT_ENOUGH;
|
|
}
|
|
iSelfProcTest++;
|
|
#else
|
|
EIS_setFrameData(&pVideoEISData->mEisHd, pEisProcPkt);
|
|
pVideoEISData->dEisGetInputFrmCnt++;
|
|
if (pVideoEISData->mEISAttr.bRetInFrmFast &&
|
|
pVideoEISData->dEisGetInputFrmCnt >= pVideoEISData->mEISAttr.iInputBufNum) {
|
|
int i = 0;
|
|
|
|
pVideoInBufTmp = VideoBufMgrGetOldestUsingFrame(pVideoEISData->pInputBufMgr);
|
|
if (pVideoInBufTmp) {
|
|
for (i = 0; i < pVideoEISData->mEISAttr.iInputBufNum; i++) {
|
|
if (pVideoEISData->pstEISPkt[i].in_addr.in_luma_mmu_Addr == pVideoInBufTmp->VFrame.mpVirAddr[0]) {
|
|
pVideoEISData->mEisPktMap &= ~(1 << i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Return input buffer to last component, must invoke [DoVideoEisSendBackInputFrame] first */
|
|
stVideoInBufRetTmp = *pVideoInBufTmp;
|
|
VideoBufMgrReleaseFrame(pVideoEISData->pInputBufMgr, pVideoInBufTmp);
|
|
DoVideoEisSendBackInputFrame(pVideoEISData, &stVideoInBufRetTmp);
|
|
} else
|
|
aloge("Using frame list empty.");
|
|
}
|
|
|
|
#ifdef PROC_TIME_TEST
|
|
TIME_INIT_START_END(T);
|
|
TIME_GET_START(T);
|
|
#endif
|
|
|
|
/* Send to kernel drivers and process it. */
|
|
iEisProcRet = EIS_Proc(&pVideoEISData->mEisHd, &iInputFrmId);
|
|
|
|
#ifdef PROC_TIME_TEST
|
|
TIME_GET_END(T);
|
|
printf("[%d]%f.\n", pVideoEISData->mMppChnInfo.mChnId, TIME_PRINT_DIFF(T));
|
|
#endif
|
|
#endif
|
|
switch (iEisProcRet) {
|
|
case LIB_S_OK: {
|
|
/* We got one processed buffer */
|
|
pEisProcPkt = &pVideoEISData->pstEISPkt[iInputFrmId];
|
|
COMP_BUFFERHEADERTYPE obh;
|
|
bool bCanGetOutBuf = 0;
|
|
|
|
bCanGetOutBuf = 0;
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
/* If we only have one output idle video frame, then keep it */
|
|
if (pVideoEISData->iOutFrmIdleCnt > 1) {
|
|
list_move_tail(&pVFrmOutputCur->mList, &pVideoEISData->mOutValidList);
|
|
pVideoEISData->iOutFrmIdleCnt--;
|
|
bCanGetOutBuf = 1;
|
|
} else{
|
|
aloge("We has only one idle frame in EIS output frame list.");
|
|
}
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
|
|
if (!pVideoEISData->mEISAttr.bRetInFrmFast) {
|
|
pVideoInBufTmp = VideoBufMgrGetSpecUsingFrameWithAddr(
|
|
pVideoEISData->pInputBufMgr, pEisProcPkt->in_addr.in_luma_mmu_Addr);
|
|
if (pVideoInBufTmp) {
|
|
/* Return input buffer to last component, must invoke [DoVideoEisSendBackInputFrame] first */
|
|
stVideoInBufRetTmp = *pVideoInBufTmp;
|
|
VideoBufMgrReleaseFrame(pVideoEISData->pInputBufMgr, pVideoInBufTmp);
|
|
DoVideoEisSendBackInputFrame(pVideoEISData, &stVideoInBufRetTmp);
|
|
} else
|
|
aloge("Not find input buffer in UsingFrameList, addr=0x%x.", pEisProcPkt->in_addr.in_luma_mmu_Addr);
|
|
/* Now, clear using flag. */
|
|
pVideoEISData->mEisPktMap &= ~(1 << iInputFrmId);
|
|
}
|
|
/* If we find one processed success video frame, then push it to next component
|
|
* or valid frame list.
|
|
*/
|
|
if (bCanGetOutBuf) {
|
|
if (pVideoInBufTmp)
|
|
pVFrmOutputCur->mFrame.VFrame.mpts = stVideoInBufRetTmp.VFrame.mpts;
|
|
else
|
|
pVFrmOutputCur->mFrame.VFrame.mpts = 0;
|
|
|
|
if (FALSE == pVideoEISData->bOutputPortTunnelFlag) {
|
|
if (pVideoEISData->bWaitingOutFrmFlag)
|
|
cdx_sem_up(&pVideoEISData->mSemWaitOutFrame);
|
|
} else if (TRUE == pVideoEISData->bOutputPortTunnelFlag && pOutputPort->hTunnel) {
|
|
MM_COMPONENTTYPE *pOutTunnelComp = (MM_COMPONENTTYPE*)pOutputPort->hTunnel;
|
|
VIDEO_FRAME_INFO_S* pVOutFrm = &pVFrmOutputCur->mFrame;
|
|
pVOutFrm->VFrame.mOffsetTop = 0;
|
|
pVOutFrm->VFrame.mOffsetBottom = pVOutFrm->VFrame.mHeight;
|
|
pVOutFrm->VFrame.mOffsetLeft = 0;
|
|
pVOutFrm->VFrame.mOffsetRight = pVOutFrm->VFrame.mWidth;
|
|
|
|
if(pVideoEISData->bStoreFrame) {
|
|
DoVideoEisStoreProcessedFrm(pVideoEISData, pVOutFrm);
|
|
pVideoEISData->bStoreFrame = FALSE;
|
|
}
|
|
|
|
pthread_mutex_lock(&pVideoEISData->mOutFrmListLock);
|
|
obh.nOutputPortIndex = pOutputPort->nPortIndex;
|
|
obh.nInputPortIndex = pOutputPort->nTunnelPortIndex;
|
|
obh.pOutputPortPrivate = pVOutFrm;
|
|
eError = COMP_EmptyThisBuffer(pOutTunnelComp, &obh);
|
|
if(SUCCESS != eError) {
|
|
alogw("Loop EIS_CompStabThread OutTunnelComp EmptyThisBuffer failed 0x%x, return this frame", eError);
|
|
/* Just return */
|
|
list_move_tail(&pVFrmOutputCur->mList, &pVideoEISData->mOutIdleList);
|
|
pVideoEISData->iOutFrmIdleCnt++;
|
|
} else
|
|
list_move_tail(&pVFrmOutputCur->mList, &pVideoEISData->mOutUsedList);
|
|
pthread_mutex_unlock(&pVideoEISData->mOutFrmListLock);
|
|
}
|
|
} else{
|
|
aloge("Not find output buffer.");
|
|
}
|
|
} break;
|
|
case LIB_E_BUFFER_NOT_ENOUGH: {
|
|
alogw("Has not get enough buffer.");
|
|
} break;
|
|
default: {
|
|
/* Something error occurs, and we should return the oldest using frame. */
|
|
if (!pVideoEISData->mEISAttr.bRetInFrmFast) {
|
|
int i = 0;
|
|
|
|
pVideoInBufTmp = VideoBufMgrGetOldestUsingFrame(pVideoEISData->pInputBufMgr);
|
|
if (pVideoInBufTmp) {
|
|
for (i = 0; i < pVideoEISData->mEISAttr.iInputBufNum; i++) {
|
|
if (pVideoEISData->pstEISPkt[i].in_addr.in_luma_mmu_Addr == pVideoInBufTmp->VFrame.mpVirAddr[0]) {
|
|
pVideoEISData->mEisPktMap &= ~(1 << i);
|
|
aloge("Free used EISPkt[%d] because of hardware error.", i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Return input buffer to last component, must invoke [DoVideoEisSendBackInputFrame] first */
|
|
stVideoInBufRetTmp = *pVideoInBufTmp;
|
|
VideoBufMgrReleaseFrame(pVideoEISData->pInputBufMgr, pVideoInBufTmp);
|
|
DoVideoEisSendBackInputFrame(pVideoEISData, &stVideoInBufRetTmp);
|
|
} else
|
|
aloge("Using frame list empty.");
|
|
}
|
|
aloge("Got one undefined error. ret 0x%x.", iEisProcRet);
|
|
} break;
|
|
}
|
|
} else {
|
|
alogv("EIS_CompStabThread not OMX_StateExecuting\n");
|
|
TMessage_WaitQueueNotEmpty(&pVideoEISData->cmd_queue, 0);
|
|
}
|
|
}
|
|
|
|
EXIT:
|
|
alogv("VideoEis ComponentThread stopped");
|
|
return (void *)SUCCESS;
|
|
}
|
|
|