PreviewCmdQueThread::update()
{
// Loop: check if next command is comming
// Next command can be {stop, precap}
// Do at least 1 frame (in case of going to precapture directly)
// --> this works when AE updates in each frame (instead of in 3 frames)
do{
//(1) 读取 处理 分配buf
updateOne();
mFrameCnt++;
//(2) handle zoom callback
handleCallback();
//(3) update check
updateCheck1();
updateCheck2();
} while( ! isNextCommand() );
}
PreviewCmdQueThread::updateOne()
{
bool ret = true;
int32_t pass1LatestBufIdx = -1;
int64_t pass1LatestTimeStamp = 0;
nsecs_t passTime = 0,pass1Time = 0,pass2Time = 0,vssTime = 0;
#if VSS_ENABLE
vector<IhwScenario::PortBufInfo> vDeBufPass1OutVss;
#endif
vector<IhwScenario::PortQTBufInfo> vDeBufPass1Out;
vector<IhwScenario::PortQTBufInfo> vDeBufPass2Out;
vector<IhwScenario::PortBufInfo> vEnBufPass2In;
vector<IhwScenario::PortBufInfo> vEnBufPass2Out;
vector<IhwScenario::PortImgInfo> vPass2Cfg;
passTime = systemTime();
//*************************************************************
// (1) [PASS 1] sensor ---> ISP --> DRAM(IMGO)
//*************************************************************
pass1Time = passTime;
//从ISP_DMA_IMGO获取Buf信息
getHw()->deque(eID_Pass1Out, &vDeBufPass1Out)
pass1Time = systemTime()-pass1Time;
//
mapQT2BufInfo(eID_Pass2In, vDeBufPass1Out, vEnBufPass2In);
mp3AHal->sendCommand(ECmd_Update);
mpEisHal->doEIS();
//*************************************************************
//(2) [PASS 2] DRAM(IMGI) --> ISP --> CDP --> DRAM (DISPO, VIDO)
// if no buffer is available, return immediately.
//*************************************************************
int32_t flag = 0;
//(.1) PASS2-IN
getCfg(eID_Pass2In , vPass2Cfg);
//(.2) PASS2-OUT
ImgBufQueNode dispNode;
ImgBufQueNode vidoNode;
mspPreviewBufHandler->dequeBuffer(eID_Pass2DISPO, dispNode);
mspPreviewBufHandler->dequeBuffer(eID_Pass2VIDO, vidoNode);
if ( dispNode.getImgBuf() != 0)
{
flag |= eID_Pass2DISPO;
IhwScenario::PortBufInfo BufInfo;
IhwScenario::PortImgInfo ImgInfo;
mapNode2BufInfo(eID_Pass2DISPO, dispNode, BufInfo);
mapNode2ImgInfo(eID_Pass2DISPO, dispNode, ImgInfo);
vEnBufPass2Out.push_back(BufInfo);
vPass2Cfg.push_back(ImgInfo);
}
if ( vidoNode.getImgBuf() != 0)
{
if( vidoNode.getCookieDE() == IPreviewBufMgr::eBuf_Rec && !mbRecording)
{
MY_LOGW("VR has been stopped, do not enque buf to pass 2");
}
else
{
flag = flag | eID_Pass2VIDO;
IhwScenario::PortBufInfo BufInfo;
IhwScenario::PortImgInfo ImgInfo;
mapNode2BufInfo(eID_Pass2VIDO, vidoNode, BufInfo);
mapNode2ImgInfo(eID_Pass2VIDO, vidoNode, ImgInfo);
vEnBufPass2Out.push_back(BufInfo);
vPass2Cfg.push_back(ImgInfo);
}
}
//(.3) no buffer ==> return immediately.
//...
//(.4) has buffer ==> do pass2 en/deque
// Note: config must be set earlier than en/de-que
//
updateZoom(vPass2Cfg);
getHw()->setConfig(&vPass2Cfg);
getHw()->enque(&vEnBufPass2In, &vEnBufPass2Out);
pass2Time = systemTime();
getHw()->deque((EHwBufIdx)flag, &vDeBufPass2Out);
pass2Time = systemTime()-pass2Time;
//*************************************************************
// (3) return buffer
//*************************************************************
if( vDeBufPass1Out.size() > 0 && vDeBufPass1Out[0].bufInfo.vBufInfo.size() > 0)
{
pass1LatestBufIdx = vDeBufPass1Out[0].bufInfo.vBufInfo.size()-1;
pass1LatestTimeStamp = vDeBufPass1Out[0].bufInfo.vBufInfo[pass1LatestBufIdx].getTimeStamp_ns();
//MY_LOGD("pass1LatestBufIdx(%d),pass1LatestTimeStamp(%lld)",pass1LatestBufIdx,pass1LatestTimeStamp);
}
//
if (ret)
{
if(checkDumpPass1())
{
dumpBuffer(vDeBufPass1Out, "pass1", "raw", mFrameCnt);
}
if (flag & eID_Pass2DISPO)
{
if(checkDumpPass2Dispo())
{
dumpImg((MUINT8*)(dispNode.getImgBuf()->getVirAddr()),
dispNode.getImgBuf()->getBufSize(), "pass2_dispo", "yuv", mFrameCnt);
}
}
if (flag & eID_Pass2VIDO)
{
if(checkDumpPass2Vido())
{
dumpImg((MUINT8*)(vidoNode.getImgBuf()->getVirAddr()),
vidoNode.getImgBuf()->getBufSize(), "pass2_vido", "yuv", mFrameCnt);
}
}
}
// (.1) return PASS1
#if VSS_ENABLE
if( mpVideoSnapshotScenario->getStatus() == IVideoSnapshotScenario::Status_WaitImage &&
pass1LatestBufIdx >= 0)
{
vector<IhwScenario::PortImgInfo> vPass1OutCfg;
IVideoSnapshotScenario::ImageInfo vssImage;
//
getCfg(eID_Pass1Out, vPass1OutCfg);
//
vssImage.size.width = vPass1OutCfg[0].u4Width;
vssImage.size.height = vPass1OutCfg[0].u4Height;
vssImage.size.stride = vPass1OutCfg[0].u4Stride[0];
vssImage.mem.id = vDeBufPass1Out[0].bufInfo.vBufInfo[pass1LatestBufIdx].memID;
vssImage.mem.vir = vDeBufPass1Out[0].bufInfo.vBufInfo[pass1LatestBufIdx].u4BufVA;
vssImage.mem.phy = vDeBufPass1Out[0].bufInfo.vBufInfo[pass1LatestBufIdx].u4BufPA;
vssImage.mem.size = vDeBufPass1Out[0].bufInfo.vBufInfo[pass1LatestBufIdx].u4BufSize;
vssImage.crop.x = vPass2Cfg[0].crop.x;
vssImage.crop.y = vPass2Cfg[0].crop.y;
vssImage.crop.w = vPass2Cfg[0].crop.w;
vssImage.crop.h = vPass2Cfg[0].crop.h;
mpVideoSnapshotScenario->setImage(vssImage);
//
mapQT2BufInfo(eID_Pass1Out, vDeBufPass1Out, vDeBufPass1OutVss);
getHw()->replaceQue(&vDeBufPass1OutVss, &mvBufPass1OutVss);
//Save the current pass 1 buffer for next VSS.
mvBufPass1OutVss.clear();
mvBufPass1OutVss.push_back(vDeBufPass1OutVss[0]);
}
else
{
#endif
getHw()->enque(vDeBufPass1Out);
#if VSS_ENABLE
}
#endif
//
#if VSS_ENABLE
vssTime = systemTime();
mpVideoSnapshotScenario->process();
vssTime = systemTime()-vssTime;
#endif
// (.2) return PASS2
if (flag & eID_Pass2DISPO)
{
dispNode.getImgBuf()->setTimestamp(pass1LatestTimeStamp);
//通知Client的接收队列,进行接收处理
mspPreviewBufHandler->enqueBuffer(dispNode);
}
//
if (flag & eID_Pass2VIDO)
{
vidoNode.getImgBuf()->setTimestamp(pass1LatestTimeStamp);
mspPreviewBufHandler->enqueBuffer(vidoNode);
}
//[T.B.D]
//'0': "SUPPOSE" DISPO and VIDO gets the same timeStamp
if( vDeBufPass2Out.size() > 1 )
{
MY_LOGW_IF(vDeBufPass2Out.at(0).bufInfo.getTimeStamp_ns() != vDeBufPass2Out.at(1).bufInfo.getTimeStamp_ns(),
"DISP(%f),VIDO(%f)", vDeBufPass2Out.at(0).bufInfo.getTimeStamp_ns(), vDeBufPass2Out.at(1).bufInfo.getTimeStamp_ns());
}
}