BOKEH_HAL *
BOKEH_HAL::createInstance(BOKEH_HAL_INIT_PARAMS *initParams)
{
return new BOKEH_HAL_IMP(initParams);
}
BOKEH_HAL_IMP::
BOKEH_HAL_IMP(
BOKEH_HAL_INIT_PARAMS *initParams)
: LOG_ENABLED( StereoSettingProvider::isLogEnabled(LOG_PERPERTY) )
, DUMP_ENABLED( checkStereoProperty(DUMP_PERPERTY) )
, DEPTH_SIZE( StereoSizeProvider::getInstance()->getBufferSize(E_DMW, eSTEREO_SCENARIO_CAPTURE) )
, __fastLogger(LOG_TAG, LOG_PERPERTY)
{
__fastLogger.setSingleLineMode(SINGLE_LINE_LOG);
//Create algo instance
__pDrv = MTKRefocus::createInstance(DRV_REFOCUS_OBJ_SW);
if(NULL == __pDrv) {
MY_LOGE("Cannot create instance of refocus");
return;
}
::memset(&__imgInfo, 0, sizeof(__imgInfo));
__initThread = std::thread(
[initParams, this]() mutable
{
MY_LOGD_IF(LOG_ENABLED, "Create BOKEH_HAL +");
__initBokeh(initParams);
__logInitData();
__dumpInitData();
MY_LOGD_IF(LOG_ENABLED, "Create BOKEH_HAL -");
});
}
void
BOKEH_HAL_IMP::__initBokeh(BOKEH_HAL_INIT_PARAMS *initParams)
{
__initTuningInfo(initParams);
__viewSize[0] = MSize(DEPTH_SIZE.w * __tuningInfo.HorzDownSampleRatio, DEPTH_SIZE.h * __tuningInfo.VertDownSampleRatio);
__viewSize[1] = MSize(DEPTH_SIZE.h * __tuningInfo.HorzDownSampleRatio, DEPTH_SIZE.w * __tuningInfo.VertDownSampleRatio);
//orientation does not matter when init, but will change in rumtime
__imgInfo.ViewWidth = __viewSize[0].w;
__imgInfo.ViewHeight = __viewSize[0].h;
__imgInfo.DepthBufferSize = DEPTH_SIZE.w * DEPTH_SIZE.h * 4;
__imgInfo.MainCamPos = static_cast<REFOCUS_MAINCAM_POS_ENUM>(StereoSettingProvider::getSensorRelativePosition());
__createWorkingBuffer();
__pDrv->RefocusInit((MUINT32 *)&__initInfo, 0);//call the algorithm // env/cb setting
}
void
BWDN_HAL_IMP::__logInitData(bool initResult)
{
if(!LOG_ENABLED) {
return;
}
FAST_LOGD("===== BWDN Init =====");
FAST_LOGD("Init result %d", initResult);
FAST_LOGD("i4CoreNum %d", __initParams.i4CoreNum);
FAST_LOGD("i4SplitSize %d", __initParams.i4SplitSize);
FAST_LOGD("fConvMat %f %f %f", __initParams.fConvMat[0],__initParams.fConvMat[1], __initParams.fConvMat[2]);
FAST_LOGD("rAcc %d", __initParams.rAcc);
FAST_LOGD("=====================");
FAST_LOG_PRINT;
}
void
BOKEH_HAL_IMP::__dumpInitData()
{
if(!DUMP_ENABLED) {
return;
}
}
void
BOKEH_HAL_IMP::__createWorkingBuffer()
{
__destroyWorkingBuffer(); //Release old buffers
//Init image info
__imgInfo.Mode = REFOCUS_MODE_FULL_SAVEAS;
__imgInfo.ImgFmt = REFOCUS_IMAGE_YUV420;
Pass2SizeInfo pass2SizeInfo;
StereoSizeProvider::getInstance()->getPass2SizeInfo(PASS2A, eSTEREO_SCENARIO_CAPTURE, pass2SizeInfo)
{
bool
StereoSizeProvider::getPass2SizeInfo(ENUM_PASS2_ROUND round, ENUM_STEREO_SCENARIO eScenario, Pass2SizeInfo &pass2SizeInfo)
{
bool isSuccess = true;
switch(round) {
case PASS2A:
pass2SizeInfo = Pass2A_SizeProvider::instance()->sizeInfo(eScenario);
if(eSTEREO_SCENARIO_CAPTURE == eScenario) {
pass2SizeInfo.areaWDMA.size = __captureSize;
}
break;
case PASS2A_2:
pass2SizeInfo = Pass2A_2_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_3:
pass2SizeInfo = Pass2A_3_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_P:
pass2SizeInfo = Pass2A_P_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_P_2:
pass2SizeInfo = Pass2A_P_2_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_P_3:
pass2SizeInfo = Pass2A_P_3_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_B:
pass2SizeInfo = Pass2A_B_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_CROP:
pass2SizeInfo = Pass2A_Crop_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_B_CROP:
pass2SizeInfo = Pass2A_B_Crop_SizeProvider::instance()->sizeInfo(eScenario);
break;
default:
isSuccess = false;
}
return isSuccess;
}//getPass2SizeInfo
}
//use pass2SizeInfo to initiate the __imgInfo's target width and height
__targetSize[0] = pass2SizeInfo.areaWDMA.size;
__targetSize[1].w = pass2SizeInfo.areaWDMA.size.h;
__targetSize[1].h = pass2SizeInfo.areaWDMA.size.w;
__imgInfo.TargetWidth = __targetSize[0].w;
__imgInfo.TargetHeight = __targetSize[0].h;
//create target image with w*h*3/2
__imgInfo.TargetImgAddr = new(std::nothrow) MUINT8[__imgInfo.TargetWidth*__imgInfo.TargetHeight*3/2];
if(NULL == __imgInfo.TargetImgAddr) {
MY_LOGE("Fail to create target image with size %dx%d", __imgInfo.TargetWidth, __imgInfo.TargetHeight);
}
//Get working buffer size
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_GET_WORKBUF_SIZE, (void *)&__imgInfo, (void *)&__initInfo.WorkingBuffSize);
__pWorkingBuf = new(std::nothrow) MUINT8[__initInfo.WorkingBuffSize];
if(NULL == __pWorkingBuf) {
MY_LOGE("Fail to create working buffer with size %d", __initInfo.WorkingBuffSize);
}
//Set working buffer
__initInfo.WorkingBuffAddr = __pWorkingBuf;
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_SET_WORKBUF_ADDR, (void *)&__initInfo, NULL);
}
//start to run
bool
BOKEH_HAL_IMP::Run(BOKEH_HAL_PARAMS ¶m, BOKEH_HAL_OUTPUT &output)
{
CPUAffinity affinity;
int core = checkStereoProperty("bokeh_core", 0);
if(core > 0) {
CPUMask cpuMask(core);
affinity.enable(cpuMask);
}
__waitInitThread();//wait init thread done ???
AutoProfileUtil profile(LOG_TAG, "BokehHALRun");
__requestNumber = param.requestNumber;
__parseExtraData(param.extraData);//parse dof level,capture orientation and focus point(coordinate)
bool bResult = true;
MY_LOGD_IF(LOG_ENABLED, "+");
__run(param, output);//run output
MY_LOGD_IF(LOG_ENABLED, "-");
if(core > 0) {
affinity.disable();
}
return bResult;
}
bool
BOKEH_HAL_IMP::__parseExtraData(char *extraData)
{
bool result = true;
// AutoProfileUtil profile(LOG_TAG, "Parse extra data");
__logExtraData(extraData);
Document document;
document.Parse(extraData);
if(document.HasParseError()) {
MY_LOGE("Fail to parse extra data %p", extraData);
result = false;
}
__dumpExtraData(document);
//Dof level
if(document.HasMember(EXTRA_DATA_DOF_LEVEL)) {
__imgInfo.DepthOfField = document["dof_level"].GetInt();
__imgInfo.DepthOfField = __imgInfo.DepthOfField*4/3;
} else {
MY_LOGE("Tag %s not found", EXTRA_DATA_DOF_LEVEL);
result = false;
}
//Capture orientation
if(document.HasMember(EXTRA_DATA_CAPTURE_ORIENTATION)) {
Value &capOrientationValue = document[EXTRA_DATA_CAPTURE_ORIENTATION];
int rotation = capOrientationValue[EXTRA_DATA_ORIENTATION].GetInt();
switch(rotation){
case 4:
rotation = 90;
break;
case 3:
rotation = 180;
break;
case 7:
rotation = 270;
break;
case 0:
default:
rotation = 0;
break;
}
__capOrientation = static_cast<ENUM_ROTATION>(rotation);
//Update depth rotation
rotation -= StereoSettingProvider::getModuleRotation();
if(rotation < 0) {
rotation += 360;
}
__depthRotation = static_cast<ENUM_ROTATION>(rotation);
int sizeIndex = (__depthRotation & 0x2 ) ? 1 : 0;
__imgInfo.TargetWidth = __targetSize[sizeIndex].w;
__imgInfo.TargetHeight = __targetSize[sizeIndex].h;
__imgInfo.ViewWidth = __viewSize[sizeIndex].w;
__imgInfo.ViewHeight = __viewSize[sizeIndex].h;
MY_LOGD_IF(LOG_ENABLED, "capOrientation %d, depthRotation %d", __capOrientation, __depthRotation);
} else {
MY_LOGE("Tag %s not found", EXTRA_DATA_CAPTURE_ORIENTATION);
result = false;
}
//Focus point (matrix coordinate)
if(document.HasMember(EXTRA_DATA_FOCUS_ROI)) {
Value &focus_roi = document[EXTRA_DATA_FOCUS_ROI];
int top = focus_roi[EXTRA_DATA_TOP].GetInt();
int bottom = focus_roi[EXTRA_DATA_BOTTOM].GetInt();
int left = focus_roi[EXTRA_DATA_LEFT].GetInt();
int right = focus_roi[EXTRA_DATA_RIGHT].GetInt();
__imgInfo.TouchCoordX = (int)(((left+right)/2.0f + 1000.0f)/2000.0f * __imgInfo.TargetWidth);
__imgInfo.TouchCoordY = (int)(((top+bottom)/2.0f + 1000.0f)/2000.0f * __imgInfo.TargetHeight);
} else {
MY_LOGE("Tag %s not found", EXTRA_DATA_FOCUS_ROI);
result = false;
}
return result;
}
void
BOKEH_HAL_IMP::__run(BOKEH_HAL_PARAMS ¶m, BOKEH_HAL_OUTPUT &output)
{
//Set image
__setImage(param);
{
AutoProfileUtil profile(LOG_TAG, "RefocusMain");
__pDrv->RefocusMain();
}
{
// AutoProfileUtil profile(LOG_TAG, "Get result");
//get a output image's info result
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_GET_RESULT, NULL, (void *)&__resultInfo);
}
//Copy result
{
AutoProfileUtil profile(LOG_TAG, "Copy bokeh image");
//get a planeSize (w x h)
size_t planeSize = __imgInfo.TargetWidth * __imgInfo.TargetHeight;
//get a yuv image's Addr
MUINT8 *src = __resultInfo.RefocusedYUVImageAddr;
//copy planeSize bytes from Addr src to __workingImage's virtual addr
::memcpy((void *)__workingImage->getBufVA(0), src, planeSize);
// addr += planeSize
src += planeSize;
//because of yuv420 4:1:1
planeSize >>= 2;
::memcpy((void *)__workingImage->getBufVA(1), src, planeSize);
src += planeSize;
::memcpy((void *)__workingImage->getBufVA(2), src, planeSize);
}
//Convert output image
{
AutoProfileUtil profile(LOG_TAG, "Convert output image");
if(!StereoDpUtil::transformImage(__workingImage.get(), output.bokehImage)) {
MY_LOGE("Fail to convert output image");
}
}
__logResult();
__dumpResult(output);
StereoDpUtil::freeImageBuffer(LOG_TAG, __workingImage);
}
void
BOKEH_HAL_IMP::__setImage(BOKEH_HAL_PARAMS ¶m)
{
AutoProfileUtil profile(LOG_TAG, "Add IMG");
// thread copyImageThread = std::thread([&]()
{
{
AutoProfileUtil profile(LOG_TAG, "SetImg Thread: Convert input image");
MSize imageSize(__imgInfo.TargetWidth, __imgInfo.TargetHeight);
//Create working image
if(StereoDpUtil::allocImageBuffer(LOG_TAG, eImgFmt_YV12, imageSize, !IS_ALLOC_GB, __workingImage)) {
if(!StereoDpUtil::transformImage(param.cleanImage, __workingImage.get(), __capOrientation)) {
MY_LOGE("Fail to convert input image");
}
} else {
MY_LOGE("Cannot create working image of size %dx%d", imageSize.w, imageSize.h);
}
}
{
AutoProfileUtil profile(LOG_TAG, "SetImg Thread: Copy input image");
size_t planeSize = __imgInfo.TargetWidth * __imgInfo.TargetHeight;
MUINT8 *dst = __imgInfo.TargetImgAddr;
::memcpy(dst, (void *)__workingImage->getBufVA(0), planeSize);
dst += planeSize;
planeSize >>= 2;
::memcpy(dst, (void *)__workingImage->getBufVA(1), planeSize);
dst += planeSize;
::memcpy(dst, (void *)__workingImage->getBufVA(2), planeSize);
}
}
// );
// copyImageThread.join();
__imgInfo.DepthBufferAddr = (MUINT8 *)param.packedDepthmap->getBufVA(0);
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_ADD_IMG, (void *)&__imgInfo, NULL);
__logImageData();
__dumpImageData(param);
}
static bool transformImage(
IImageBuffer *imgSrc,
IImageBuffer *imgDst,
ENUM_ROTATION eRotateDegree = eRotate_0,
DpRect *srcROI = NULL,
DpRect *dstROI = NULL
)
{
if(NULL == imgSrc ||
NULL == imgDst)
{
return false;
}
DpBlitStream dpStream;
void *pBuffer[PLANE_COUNT];
uint32_t size[PLANE_COUNT];
//Set src
pBuffer[0] = (imgSrc->getPlaneCount() > 0) ? (void *)imgSrc->getBufVA(0) : NULL;
pBuffer[1] = (imgSrc->getPlaneCount() > 1) ? (void *)imgSrc->getBufVA(1) : NULL;
pBuffer[2] = (imgSrc->getPlaneCount() > 2) ? (void *)imgSrc->getBufVA(2) : NULL;
size[0] = (imgSrc->getPlaneCount() > 0) ? imgSrc->getBufSizeInBytes(0) : 0;
size[1] = (imgSrc->getPlaneCount() > 1) ? imgSrc->getBufSizeInBytes(1) : 0;
size[2] = (imgSrc->getPlaneCount() > 2) ? imgSrc->getBufSizeInBytes(2) : 0;
dpStream.setSrcBuffer(pBuffer, size, imgSrc->getPlaneCount());
//Only support YV12, RGBA, Y8, NV12, NV21
DpColorFormat imgFormat = __getDpImageFormat(imgSrc);
if(DP_COLOR_UNKNOWN == imgFormat) {
__android_log_print(ANDROID_LOG_ERROR, STEREO_DP_UTIL_TAG, "Unknown src format: 0x%x", imgSrc->getImgFormat());
return false;
}
dpStream.setSrcConfig(imgSrc->getImgSize().w,
imgSrc->getImgSize().h,
imgSrc->getBufStridesInBytes(0),
(imgSrc->getPlaneCount() <= 1) ? 0 : imgSrc->getBufStridesInBytes(1),
imgFormat,
DP_PROFILE_FULL_BT601,
eInterlace_None,
srcROI,
DP_SECURE_NONE,
DO_FLUSH);
// Set dst
void *pBufferOut[PLANE_COUNT];
uint32_t sizeOut[PLANE_COUNT];
pBufferOut[0] = (imgDst->getPlaneCount() > 0) ? (void *)imgDst->getBufVA(0) : NULL;
pBufferOut[1] = (imgDst->getPlaneCount() > 1) ? (void *)imgDst->getBufVA(1) : NULL;
pBufferOut[2] = (imgDst->getPlaneCount() > 2) ? (void *)imgDst->getBufVA(2) : NULL;
sizeOut[0] = (imgDst->getPlaneCount() > 0) ? imgDst->getBufSizeInBytes(0) : 0;
sizeOut[1] = (imgDst->getPlaneCount() > 1) ? imgDst->getBufSizeInBytes(1) : 0;
sizeOut[2] = (imgDst->getPlaneCount() > 2) ? imgDst->getBufSizeInBytes(2) : 0;
dpStream.setDstBuffer(pBufferOut, sizeOut, imgDst->getPlaneCount());
//Only support YV12, RGBA, Y8, NV12, NV21
imgFormat = __getDpImageFormat(imgDst);
if(DP_COLOR_UNKNOWN == imgFormat) {
__android_log_print(ANDROID_LOG_ERROR, STEREO_DP_UTIL_TAG, "Unknown dst format: 0x%x", imgDst->getImgFormat());
return false;
}
if(dstROI) {
dpStream.setDstConfig(dstROI->w,
dstROI->h,
imgDst->getBufStridesInBytes(0),
(imgDst->getPlaneCount() <= 1) ? 0 : imgDst->getBufStridesInBytes(1),
imgFormat,
DP_PROFILE_FULL_BT601,
eInterlace_None,
dstROI,
DP_SECURE_NONE,
DO_FLUSH);
} else {
dpStream.setDstConfig(imgDst->getImgSize().w,
imgDst->getImgSize().h,
imgDst->getBufStridesInBytes(0),
(imgDst->getPlaneCount() <= 1) ? 0 : imgDst->getBufStridesInBytes(1),
imgFormat,
DP_PROFILE_FULL_BT601,
eInterlace_None,
NULL,
DP_SECURE_NONE,
DO_FLUSH);
}
dpStream.setRotate(eRotateDegree);
dpStream.invalidate();
return true;
}
BOKEH_HAL::createInstance(BOKEH_HAL_INIT_PARAMS *initParams)
{
return new BOKEH_HAL_IMP(initParams);
}
BOKEH_HAL_IMP::
BOKEH_HAL_IMP(
BOKEH_HAL_INIT_PARAMS *initParams)
: LOG_ENABLED( StereoSettingProvider::isLogEnabled(LOG_PERPERTY) )
, DUMP_ENABLED( checkStereoProperty(DUMP_PERPERTY) )
, DEPTH_SIZE( StereoSizeProvider::getInstance()->getBufferSize(E_DMW, eSTEREO_SCENARIO_CAPTURE) )
, __fastLogger(LOG_TAG, LOG_PERPERTY)
{
__fastLogger.setSingleLineMode(SINGLE_LINE_LOG);
//Create algo instance
__pDrv = MTKRefocus::createInstance(DRV_REFOCUS_OBJ_SW);
if(NULL == __pDrv) {
MY_LOGE("Cannot create instance of refocus");
return;
}
::memset(&__imgInfo, 0, sizeof(__imgInfo));
__initThread = std::thread(
[initParams, this]() mutable
{
MY_LOGD_IF(LOG_ENABLED, "Create BOKEH_HAL +");
__initBokeh(initParams);
__logInitData();
__dumpInitData();
MY_LOGD_IF(LOG_ENABLED, "Create BOKEH_HAL -");
});
}
void
BOKEH_HAL_IMP::__initBokeh(BOKEH_HAL_INIT_PARAMS *initParams)
{
__initTuningInfo(initParams);
__viewSize[0] = MSize(DEPTH_SIZE.w * __tuningInfo.HorzDownSampleRatio, DEPTH_SIZE.h * __tuningInfo.VertDownSampleRatio);
__viewSize[1] = MSize(DEPTH_SIZE.h * __tuningInfo.HorzDownSampleRatio, DEPTH_SIZE.w * __tuningInfo.VertDownSampleRatio);
//orientation does not matter when init, but will change in rumtime
__imgInfo.ViewWidth = __viewSize[0].w;
__imgInfo.ViewHeight = __viewSize[0].h;
__imgInfo.DepthBufferSize = DEPTH_SIZE.w * DEPTH_SIZE.h * 4;
__imgInfo.MainCamPos = static_cast<REFOCUS_MAINCAM_POS_ENUM>(StereoSettingProvider::getSensorRelativePosition());
__createWorkingBuffer();
__pDrv->RefocusInit((MUINT32 *)&__initInfo, 0);//call the algorithm // env/cb setting
}
void
BWDN_HAL_IMP::__logInitData(bool initResult)
{
if(!LOG_ENABLED) {
return;
}
FAST_LOGD("===== BWDN Init =====");
FAST_LOGD("Init result %d", initResult);
FAST_LOGD("i4CoreNum %d", __initParams.i4CoreNum);
FAST_LOGD("i4SplitSize %d", __initParams.i4SplitSize);
FAST_LOGD("fConvMat %f %f %f", __initParams.fConvMat[0],__initParams.fConvMat[1], __initParams.fConvMat[2]);
FAST_LOGD("rAcc %d", __initParams.rAcc);
FAST_LOGD("=====================");
FAST_LOG_PRINT;
}
void
BOKEH_HAL_IMP::__dumpInitData()
{
if(!DUMP_ENABLED) {
return;
}
}
void
BOKEH_HAL_IMP::__createWorkingBuffer()
{
__destroyWorkingBuffer(); //Release old buffers
//Init image info
__imgInfo.Mode = REFOCUS_MODE_FULL_SAVEAS;
__imgInfo.ImgFmt = REFOCUS_IMAGE_YUV420;
Pass2SizeInfo pass2SizeInfo;
StereoSizeProvider::getInstance()->getPass2SizeInfo(PASS2A, eSTEREO_SCENARIO_CAPTURE, pass2SizeInfo)
{
bool
StereoSizeProvider::getPass2SizeInfo(ENUM_PASS2_ROUND round, ENUM_STEREO_SCENARIO eScenario, Pass2SizeInfo &pass2SizeInfo)
{
bool isSuccess = true;
switch(round) {
case PASS2A:
pass2SizeInfo = Pass2A_SizeProvider::instance()->sizeInfo(eScenario);
if(eSTEREO_SCENARIO_CAPTURE == eScenario) {
pass2SizeInfo.areaWDMA.size = __captureSize;
}
break;
case PASS2A_2:
pass2SizeInfo = Pass2A_2_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_3:
pass2SizeInfo = Pass2A_3_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_P:
pass2SizeInfo = Pass2A_P_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_P_2:
pass2SizeInfo = Pass2A_P_2_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_P_3:
pass2SizeInfo = Pass2A_P_3_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_B:
pass2SizeInfo = Pass2A_B_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_CROP:
pass2SizeInfo = Pass2A_Crop_SizeProvider::instance()->sizeInfo(eScenario);
break;
case PASS2A_B_CROP:
pass2SizeInfo = Pass2A_B_Crop_SizeProvider::instance()->sizeInfo(eScenario);
break;
default:
isSuccess = false;
}
return isSuccess;
}//getPass2SizeInfo
}
//use pass2SizeInfo to initiate the __imgInfo's target width and height
__targetSize[0] = pass2SizeInfo.areaWDMA.size;
__targetSize[1].w = pass2SizeInfo.areaWDMA.size.h;
__targetSize[1].h = pass2SizeInfo.areaWDMA.size.w;
__imgInfo.TargetWidth = __targetSize[0].w;
__imgInfo.TargetHeight = __targetSize[0].h;
//create target image with w*h*3/2
__imgInfo.TargetImgAddr = new(std::nothrow) MUINT8[__imgInfo.TargetWidth*__imgInfo.TargetHeight*3/2];
if(NULL == __imgInfo.TargetImgAddr) {
MY_LOGE("Fail to create target image with size %dx%d", __imgInfo.TargetWidth, __imgInfo.TargetHeight);
}
//Get working buffer size
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_GET_WORKBUF_SIZE, (void *)&__imgInfo, (void *)&__initInfo.WorkingBuffSize);
__pWorkingBuf = new(std::nothrow) MUINT8[__initInfo.WorkingBuffSize];
if(NULL == __pWorkingBuf) {
MY_LOGE("Fail to create working buffer with size %d", __initInfo.WorkingBuffSize);
}
//Set working buffer
__initInfo.WorkingBuffAddr = __pWorkingBuf;
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_SET_WORKBUF_ADDR, (void *)&__initInfo, NULL);
}
//start to run
bool
BOKEH_HAL_IMP::Run(BOKEH_HAL_PARAMS ¶m, BOKEH_HAL_OUTPUT &output)
{
CPUAffinity affinity;
int core = checkStereoProperty("bokeh_core", 0);
if(core > 0) {
CPUMask cpuMask(core);
affinity.enable(cpuMask);
}
__waitInitThread();//wait init thread done ???
AutoProfileUtil profile(LOG_TAG, "BokehHALRun");
__requestNumber = param.requestNumber;
__parseExtraData(param.extraData);//parse dof level,capture orientation and focus point(coordinate)
bool bResult = true;
MY_LOGD_IF(LOG_ENABLED, "+");
__run(param, output);//run output
MY_LOGD_IF(LOG_ENABLED, "-");
if(core > 0) {
affinity.disable();
}
return bResult;
}
bool
BOKEH_HAL_IMP::__parseExtraData(char *extraData)
{
bool result = true;
// AutoProfileUtil profile(LOG_TAG, "Parse extra data");
__logExtraData(extraData);
Document document;
document.Parse(extraData);
if(document.HasParseError()) {
MY_LOGE("Fail to parse extra data %p", extraData);
result = false;
}
__dumpExtraData(document);
//Dof level
if(document.HasMember(EXTRA_DATA_DOF_LEVEL)) {
__imgInfo.DepthOfField = document["dof_level"].GetInt();
__imgInfo.DepthOfField = __imgInfo.DepthOfField*4/3;
} else {
MY_LOGE("Tag %s not found", EXTRA_DATA_DOF_LEVEL);
result = false;
}
//Capture orientation
if(document.HasMember(EXTRA_DATA_CAPTURE_ORIENTATION)) {
Value &capOrientationValue = document[EXTRA_DATA_CAPTURE_ORIENTATION];
int rotation = capOrientationValue[EXTRA_DATA_ORIENTATION].GetInt();
switch(rotation){
case 4:
rotation = 90;
break;
case 3:
rotation = 180;
break;
case 7:
rotation = 270;
break;
case 0:
default:
rotation = 0;
break;
}
__capOrientation = static_cast<ENUM_ROTATION>(rotation);
//Update depth rotation
rotation -= StereoSettingProvider::getModuleRotation();
if(rotation < 0) {
rotation += 360;
}
__depthRotation = static_cast<ENUM_ROTATION>(rotation);
int sizeIndex = (__depthRotation & 0x2 ) ? 1 : 0;
__imgInfo.TargetWidth = __targetSize[sizeIndex].w;
__imgInfo.TargetHeight = __targetSize[sizeIndex].h;
__imgInfo.ViewWidth = __viewSize[sizeIndex].w;
__imgInfo.ViewHeight = __viewSize[sizeIndex].h;
MY_LOGD_IF(LOG_ENABLED, "capOrientation %d, depthRotation %d", __capOrientation, __depthRotation);
} else {
MY_LOGE("Tag %s not found", EXTRA_DATA_CAPTURE_ORIENTATION);
result = false;
}
//Focus point (matrix coordinate)
if(document.HasMember(EXTRA_DATA_FOCUS_ROI)) {
Value &focus_roi = document[EXTRA_DATA_FOCUS_ROI];
int top = focus_roi[EXTRA_DATA_TOP].GetInt();
int bottom = focus_roi[EXTRA_DATA_BOTTOM].GetInt();
int left = focus_roi[EXTRA_DATA_LEFT].GetInt();
int right = focus_roi[EXTRA_DATA_RIGHT].GetInt();
__imgInfo.TouchCoordX = (int)(((left+right)/2.0f + 1000.0f)/2000.0f * __imgInfo.TargetWidth);
__imgInfo.TouchCoordY = (int)(((top+bottom)/2.0f + 1000.0f)/2000.0f * __imgInfo.TargetHeight);
} else {
MY_LOGE("Tag %s not found", EXTRA_DATA_FOCUS_ROI);
result = false;
}
return result;
}
void
BOKEH_HAL_IMP::__run(BOKEH_HAL_PARAMS ¶m, BOKEH_HAL_OUTPUT &output)
{
//Set image
__setImage(param);
{
AutoProfileUtil profile(LOG_TAG, "RefocusMain");
__pDrv->RefocusMain();
}
{
// AutoProfileUtil profile(LOG_TAG, "Get result");
//get a output image's info result
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_GET_RESULT, NULL, (void *)&__resultInfo);
}
//Copy result
{
AutoProfileUtil profile(LOG_TAG, "Copy bokeh image");
//get a planeSize (w x h)
size_t planeSize = __imgInfo.TargetWidth * __imgInfo.TargetHeight;
//get a yuv image's Addr
MUINT8 *src = __resultInfo.RefocusedYUVImageAddr;
//copy planeSize bytes from Addr src to __workingImage's virtual addr
::memcpy((void *)__workingImage->getBufVA(0), src, planeSize);
// addr += planeSize
src += planeSize;
//because of yuv420 4:1:1
planeSize >>= 2;
::memcpy((void *)__workingImage->getBufVA(1), src, planeSize);
src += planeSize;
::memcpy((void *)__workingImage->getBufVA(2), src, planeSize);
}
//Convert output image
{
AutoProfileUtil profile(LOG_TAG, "Convert output image");
if(!StereoDpUtil::transformImage(__workingImage.get(), output.bokehImage)) {
MY_LOGE("Fail to convert output image");
}
}
__logResult();
__dumpResult(output);
StereoDpUtil::freeImageBuffer(LOG_TAG, __workingImage);
}
void
BOKEH_HAL_IMP::__setImage(BOKEH_HAL_PARAMS ¶m)
{
AutoProfileUtil profile(LOG_TAG, "Add IMG");
// thread copyImageThread = std::thread([&]()
{
{
AutoProfileUtil profile(LOG_TAG, "SetImg Thread: Convert input image");
MSize imageSize(__imgInfo.TargetWidth, __imgInfo.TargetHeight);
//Create working image
if(StereoDpUtil::allocImageBuffer(LOG_TAG, eImgFmt_YV12, imageSize, !IS_ALLOC_GB, __workingImage)) {
if(!StereoDpUtil::transformImage(param.cleanImage, __workingImage.get(), __capOrientation)) {
MY_LOGE("Fail to convert input image");
}
} else {
MY_LOGE("Cannot create working image of size %dx%d", imageSize.w, imageSize.h);
}
}
{
AutoProfileUtil profile(LOG_TAG, "SetImg Thread: Copy input image");
size_t planeSize = __imgInfo.TargetWidth * __imgInfo.TargetHeight;
MUINT8 *dst = __imgInfo.TargetImgAddr;
::memcpy(dst, (void *)__workingImage->getBufVA(0), planeSize);
dst += planeSize;
planeSize >>= 2;
::memcpy(dst, (void *)__workingImage->getBufVA(1), planeSize);
dst += planeSize;
::memcpy(dst, (void *)__workingImage->getBufVA(2), planeSize);
}
}
// );
// copyImageThread.join();
__imgInfo.DepthBufferAddr = (MUINT8 *)param.packedDepthmap->getBufVA(0);
__pDrv->RefocusFeatureCtrl(REFOCUS_FEATURE_ADD_IMG, (void *)&__imgInfo, NULL);
__logImageData();
__dumpImageData(param);
}
static bool transformImage(
IImageBuffer *imgSrc,
IImageBuffer *imgDst,
ENUM_ROTATION eRotateDegree = eRotate_0,
DpRect *srcROI = NULL,
DpRect *dstROI = NULL
)
{
if(NULL == imgSrc ||
NULL == imgDst)
{
return false;
}
DpBlitStream dpStream;
void *pBuffer[PLANE_COUNT];
uint32_t size[PLANE_COUNT];
//Set src
pBuffer[0] = (imgSrc->getPlaneCount() > 0) ? (void *)imgSrc->getBufVA(0) : NULL;
pBuffer[1] = (imgSrc->getPlaneCount() > 1) ? (void *)imgSrc->getBufVA(1) : NULL;
pBuffer[2] = (imgSrc->getPlaneCount() > 2) ? (void *)imgSrc->getBufVA(2) : NULL;
size[0] = (imgSrc->getPlaneCount() > 0) ? imgSrc->getBufSizeInBytes(0) : 0;
size[1] = (imgSrc->getPlaneCount() > 1) ? imgSrc->getBufSizeInBytes(1) : 0;
size[2] = (imgSrc->getPlaneCount() > 2) ? imgSrc->getBufSizeInBytes(2) : 0;
dpStream.setSrcBuffer(pBuffer, size, imgSrc->getPlaneCount());
//Only support YV12, RGBA, Y8, NV12, NV21
DpColorFormat imgFormat = __getDpImageFormat(imgSrc);
if(DP_COLOR_UNKNOWN == imgFormat) {
__android_log_print(ANDROID_LOG_ERROR, STEREO_DP_UTIL_TAG, "Unknown src format: 0x%x", imgSrc->getImgFormat());
return false;
}
dpStream.setSrcConfig(imgSrc->getImgSize().w,
imgSrc->getImgSize().h,
imgSrc->getBufStridesInBytes(0),
(imgSrc->getPlaneCount() <= 1) ? 0 : imgSrc->getBufStridesInBytes(1),
imgFormat,
DP_PROFILE_FULL_BT601,
eInterlace_None,
srcROI,
DP_SECURE_NONE,
DO_FLUSH);
// Set dst
void *pBufferOut[PLANE_COUNT];
uint32_t sizeOut[PLANE_COUNT];
pBufferOut[0] = (imgDst->getPlaneCount() > 0) ? (void *)imgDst->getBufVA(0) : NULL;
pBufferOut[1] = (imgDst->getPlaneCount() > 1) ? (void *)imgDst->getBufVA(1) : NULL;
pBufferOut[2] = (imgDst->getPlaneCount() > 2) ? (void *)imgDst->getBufVA(2) : NULL;
sizeOut[0] = (imgDst->getPlaneCount() > 0) ? imgDst->getBufSizeInBytes(0) : 0;
sizeOut[1] = (imgDst->getPlaneCount() > 1) ? imgDst->getBufSizeInBytes(1) : 0;
sizeOut[2] = (imgDst->getPlaneCount() > 2) ? imgDst->getBufSizeInBytes(2) : 0;
dpStream.setDstBuffer(pBufferOut, sizeOut, imgDst->getPlaneCount());
//Only support YV12, RGBA, Y8, NV12, NV21
imgFormat = __getDpImageFormat(imgDst);
if(DP_COLOR_UNKNOWN == imgFormat) {
__android_log_print(ANDROID_LOG_ERROR, STEREO_DP_UTIL_TAG, "Unknown dst format: 0x%x", imgDst->getImgFormat());
return false;
}
if(dstROI) {
dpStream.setDstConfig(dstROI->w,
dstROI->h,
imgDst->getBufStridesInBytes(0),
(imgDst->getPlaneCount() <= 1) ? 0 : imgDst->getBufStridesInBytes(1),
imgFormat,
DP_PROFILE_FULL_BT601,
eInterlace_None,
dstROI,
DP_SECURE_NONE,
DO_FLUSH);
} else {
dpStream.setDstConfig(imgDst->getImgSize().w,
imgDst->getImgSize().h,
imgDst->getBufStridesInBytes(0),
(imgDst->getPlaneCount() <= 1) ? 0 : imgDst->getBufStridesInBytes(1),
imgFormat,
DP_PROFILE_FULL_BT601,
eInterlace_None,
NULL,
DP_SECURE_NONE,
DO_FLUSH);
}
dpStream.setRotate(eRotateDegree);
dpStream.invalidate();
return true;
}