bokeh

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 &param, 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 &param, 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 &param)
{
    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;
    }

























發佈了46 篇原創文章 · 獲贊 11 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章