CAMERA预览数据流程分析(一)-------数据的获取

预览数据流分析(一)  数据的获取

 

mCameraDevice.startPreview();

 

/*

上篇文章已经有知道这个mCameraDevice就是对应的CameraClient的客户端,所以这个的startPreview就是CameraClient::startPreview()

*/

Step 1:

\frameworks\av\services\camera\libcameraservice\api1\CameraClient.cpp

// start preview mode

status_t CameraClient::startPreview() {

   LOG1("startPreview (pid %d)", getCallingPid());

   return startCameraMode(CAMERA_PREVIEW_MODE);

}

 

Step 2:

\frameworks\av\services\camera\libcameraservice\api1\CameraClient.cpp

 

// start preview or recording

status_tCameraClient::startCameraMode(camera_mode mode) {

   LOG1("startCameraMode(%d)", mode);

   Mutex::Autolock lock(mLock);

   status_t result = checkPidAndHardware();

   if (result != NO_ERROR) return result;

 

   switch(mode) {

       case CAMERA_PREVIEW_MODE:

           if (mSurface == 0 && mPreviewWindow == 0) {

                LOG1("mSurface is not setyet.");

               // still able to startpreview in this case.

           }

           return startPreviewMode();

       case CAMERA_RECORDING_MODE:

           if (mSurface == 0 && mPreviewWindow == 0) {

                ALOGE("mSurface ormPreviewWindow must be set before startRecordingMode.");

                return INVALID_OPERATION;

           }

           return startRecordingMode();

       default:

           return UNKNOWN_ERROR;

    }

}

 

Step 3:

\frameworks\av\services\camera\libcameraservice\api1\CameraClient.cpp

 

status_t CameraClient::startPreviewMode() {

   LOG1("startPreviewMode");

   status_t result = NO_ERROR;

 

   // if preview has been enabled, nothing needs to be done

   if (mHardware->previewEnabled()) {

       return NO_ERROR;

    }

 

   if (mPreviewWindow != 0) {

       native_window_set_scaling_mode(mPreviewWindow.get(),

               NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);

       native_window_set_buffers_transform(mPreviewWindow.get(),

                mOrientation);

    }

    mHardware->setPreviewWindow(mPreviewWindow);

   result = mHardware->startPreview();

 

   return result;

}

 

/*

主要分析这两个接口:

1,  mHardware->setPreviewWindow

2,  mHardware->startPreview();

mHardware前面已经有说明说,对应的就是Cam1Device类,而其具体的实现则是在其父类Cam1DeviceBase中实现的。所以mHardware->setPreviewWindow

对应就是Cam1DeviceBase::

setPreviewWindow(preview_stream_ops*window)

mHardware->startPreview();对应的是status_t

Cam1DeviceBase::

startPreview()

*/

 

Step 4.1.1:

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device\Cam1DeviceBase.cpp

status_t

Cam1DeviceBase::

setPreviewWindow(preview_stream_ops* window)

{

   CAM_TRACE_CALL();

   MY_LOGI("+ window(%p)", window);

/*

这里主要是初始化了一个DisplayClient的类。具体这个DisplayClient的功能。后面再分析。

DisplayClient创建的时候,生成了一个createDisplayThread的线程,用来处理displayclient发送过来的消息,

createImgBufQueue 则用于存储数据,具体如何运作的待分析。

bool

DisplayClient::

init()

{

    bool ret =false;

    //

   MY_LOGD("+");

    //

    ret =   createDisplayThread()

       &&  createImgBufQueue()

            ;

    //

    MY_LOGD("-ret(%d)", ret);

    return  ret;

}

*/

   status_t status = initDisplayClient(window);

   if  ( OK == status &&previewEnabled() && mpDisplayClient != 0 )

    {

       status = enableDisplayClient();

       if(mbWindowReady)

       {

           waitStartPreviewDone();

       }

    }

   //

   return  status;

}

 

Step 4.1.2:

 

status_t

Cam1DeviceBase::

initDisplayClient(preview_stream_ops*window)

{

   CAM_TRACE_CALL();

#if '1'!=MTKCAM_HAVE_DISPLAY_CLIENT

   #warning "Not Build Display Client"

   MY_LOGD("Not Build Display Client");

   return  OK;

#else

   status_t status = OK;

   Size previewSize;

   //

   MY_LOGD("+ window(%p)", window);

   //

   //

   //  [1] Check to see whether thepassed window is NULL or not.

   if  ( ! window )

    {

       MY_LOGW("NULL window is passed into...");

       mbWindowReady = false;

       //

       if  ( mpDisplayClient != 0 )

       {

           MY_LOGW("destroy the current display client(%p)...",mpDisplayClient.get());

           mpDisplayClient->uninit();

           mpDisplayClient.clear();

       }

       status = OK;

       goto lbExit;

    }

   mbWindowReady = true;

   //

   //

   //  [2] Get preview size.

   if  ( !queryPreviewSize(previewSize.width, previewSize.height) )

    {

       MY_LOGE("queryPreviewSize");

       status = DEAD_OBJECT;

       goto lbExit;

    }

   //

   //

   //  [3] Initialize Display Client.

   if  ( mpDisplayClient != 0 )

    {

       if  ( previewEnabled() )

       {

           MY_LOGW("Do nothing since Display Client(%p) is already createdafter startPreview()", mpDisplayClient.get());

//         This method must be called before startPreview(). The one exception isthat

//         if the preview surface texture is not set (or set to null) beforestartPreview() is called,

//         then this method may be called once with a non-null parameter to set thepreview surface.

           status = OK;

           goto lbExit;

       }

       else

       {

           MY_LOGW("New window is set after stopPreview or takePicture.Destroy the current display client(%p)...", mpDisplayClient.get());

           mpDisplayClient->uninit();

           mpDisplayClient.clear();

       }

    }

   //  [3.1] create a Display Client.

   mpDisplayClient = IDisplayClient::createInstance();

   if  ( mpDisplayClient == 0 )

    {

       MY_LOGE("Cannot create mpDisplayClient");

       status = NO_MEMORY;

       goto lbExit;

    }

   //  Display Rotation

   if(mpParamsMgr->getDisplayRotationSupported())

    {

       MY_LOGD("orientation = %d", mOrientation);

       mpDisplayClient->SetOrientationForDisplay(mOrientation);

    }

   //  [3.2] initialize thenewly-created Display Client.

   if  ( ! mpDisplayClient->init())

    {

        MY_LOGE("mpDisplayClient init()failed");

       mpDisplayClient->uninit();

       mpDisplayClient.clear();

       status = NO_MEMORY;

       goto lbExit;

    }

   //  [3.3] set preview_stream_ops& related window info.

   if  ( ! mpDisplayClient->setWindow(window,previewSize.width, previewSize.height, queryDisplayBufCount()) )

    {

       status = INVALID_OPERATION;

       goto lbExit;

    }

   //  [3.4] set Image BufferProvider Client if it exist.

   if  ( mpCamAdapter != 0 &&! mpDisplayClient->setImgBufProviderClient(mpCamAdapter) )

    {

       status = INVALID_OPERATION;

       goto lbExit;

    }

   //

   //

   status = OK;

   //

lbExit:

   if  ( OK != status )

    {

       MY_LOGD("Cleanup...");

       mpDisplayClient->uninit();

       mpDisplayClient.clear();

    }

   //

   MY_LOGD("- status(%d)", status);

   return  status;

#endif//MTKCAM_HAVE_DISPLAY_CLIENT

}

 

Step 4.1.3:

 

status_t

Cam1DeviceBase::

enableDisplayClient()

{

   status_t status = OK;

   Size previewSize;

   //

   MY_LOGD("+");

   //

   //  [1] Get preview size.

   if  ( !queryPreviewSize(previewSize.width, previewSize.height) )

    {

       MY_LOGE("queryPreviewSize");

       status = DEAD_OBJECT;

       goto lbExit;

    }

    //

   if(mpParamsMgr->getIfFirstPreviewFrameAsBlack())

    {

       mpDisplayClient->setFirstFrameBlack();

       mpParamsMgr->set(MtkCameraParameters::KEY_FIRST_PREVIEW_FRAME_BLACK,0);

    }

   //  [2] Enable

   if  ( !mpDisplayClient->enableDisplay(previewSize.width, previewSize.height,queryDisplayBufCount(), mpCamAdapter) )

    {

       MY_LOGE("mpDisplayClient(%p)->enableDisplay()",mpDisplayClient.get());

       status = INVALID_OPERATION;

       goto lbExit;

    }

   //

   status = OK;

lbExit:

   MY_LOGD("- status(%d)",status);

   return  status;

}

 

4.2.1:

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device\Cam1DeviceBase.cpp

/*

这个是preview的具体实现过程,很重要的一个函数。

*/

status_t

Cam1DeviceBase::

startPreview()

{

   CAM_TRACE_CALL();

   MY_LOGI("+");

   //

   status_t status = OK;

   bool usePreviewThread = false;

   //

   if( mpParamsMgr->getIfFirstPreviewFrameAsBlack() &&

       mbWindowReady == false)

    {

       usePreviewThread = true;

       disableWaitSensorThread(true);

    }

   //

    {

       CAM_TRACE_NAME("deviceStartPreview");

       if  ( mpCamAdapter != 0 &&mpCamAdapter->isTakingPicture() )

       {

           MY_LOGE("Capture is not done");

           status = INVALID_OPERATION;

           return  status;

       }

       //

       if  ( previewEnabled() )

       {

           MY_LOGD("Preview already running");

           status = ALREADY_EXISTS;

           return  status;

       }

/*

onStartPreview主要是初始化了一个CameraAdapter的类,用于提供BUFF数据,并且将该类设置到displayclient camclient中去了。具体过程可以参照:

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device\Cam1DeviceBase.cpp

initCameraAdapter

*/

       if  ( ! onStartPreview())

       {

           MY_LOGE("onStartPreviewLocked() fail");

           status = INVALID_OPERATION;

           goto lbExit;

       }

    }

   //

    {

       CAM_TRACE_NAME("clientStartPreview");

       if  ( mpDisplayClient == 0 )

       {

           MY_LOGD("DisplayClient is not ready.");

       }

/*

displayclinet进行了相关设置,将数据输出到pStreamOps,这个就是我们要输出的数据。具体如何使用的,待学习。

mpDisplayClient->enableDisplay(previewSize.width,previewSize.height, queryDisplayBufCount(), mpCamAdapter)

*/

       else if ( OK != (status = enableDisplayClient()))

       {

           goto lbExit;

       }

       //

       if  ( mpCamClient != 0 )

       {

/*

这里这个CamClient想说明下,以前与CameraClient搞混淆了。这里的CamClient对应的是:

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\CamClient\CamClient.cpp

里面有previewClientrecoudClient,这里只关心previewClient .里面主要是设置了相关参数,申请了一块BUFF

bool

PreviewClient::

initBuffers()

{

    bool ret = false;

    //

    // (1) Lock

    Mutex::Autolock _l(mModuleMtx);

    //

    // (2) Allocate buffers.

    muImgBufIdx = 0;

 

    mpImgBufMgr = ImgBufManager::alloc(

                    ms8PrvTgtFmt,

                    mi4PrvWidth,

                    mi4PrvHeight,

                    eMAX_PREVIEW_BUFFER_NUM,

                   "PreviewClientCb",

                    mpCamMsgCbInfo->mRequestMemory,

                    0,

                    0);

    if  (mpImgBufMgr == 0 )

    {

        MY_LOGE("ImgBufManager::alloc()fail");

        goto lbExit;

    }

    //

    //

    mpExtImgProc =ExtImgProc::createInstance();

    if(mpExtImgProc != NULL)

    {

        mpExtImgProc->init();

    }

    //

    //

    ret = true;

lbExit:

    return ret;

}

*/

           if  ( ! mpCamClient->startPreview())

           {

                status = INVALID_OPERATION;

                goto lbExit;

           }

       }

       // forward to registered clients

       Vector >::const_iterator it;

       for (it = vmpCamClient.begin(); it != vmpCamClient.end(); ++it)

       {

           (*it)->startPreview();

       }

    }

 

    //

   //  startPreview in CameraAdapter.

    {

       if(usePreviewThread)

       {

           if( pthread_create(&mStartPreviewTThreadHandle, NULL,startPreviewThread, this) != 0 )

           {

                ALOGE("startPreviewpthread create failed");

           }

       }

       else

       {

           CAM_TRACE_NAME("adapterStartPreview");

/*

下面的步骤重点跟进下mpCamAdapter->startPreview();

*/

           status = mpCamAdapter->startPreview();

           if  ( OK != status )

           {

                MY_LOGE("startPreview() inCameraAdapter returns: [%s(%d)]", ::strerror(-status), -status);

                goto lbExit;

           }

       }

    }

   //

   //

   enableMsgType(CAMERA_MSG_PREVIEW_METADATA);

   //

   mIsPreviewEnabled = true;

   //

   status = OK;

lbExit:

   if  ( OK != status )

    {

       MY_LOGD("Cleanup after error");

       //

       if  ( mpCamClient != 0 )

       {

           mpCamClient->stopPreview();

       }

       // forward to registered clients

       Vector >::const_iterator it;

       for (it = vmpCamClient.begin(); it != vmpCamClient.end(); ++it)

       {

           (*it)->stopPreview();

       }

       //

       disableDisplayClient();

    }

   //

   MY_LOGI("- status(%d)", status);

   return  status;

}

 

Step 4.2.2:

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt8127\v1\hal\adapter\MtkDefault\Preview\MtkDefaultCamAdapter.Preview.cpp

status_t

CamAdapter::

startPreview()

{

   return  mpStateManager->getCurrentState()->onStartPreview(this);

}

 

Step 4.2.3:

/*

mpStateManager->getCurrentState()->onStartPreview(this);onHandleStartPreview的转换下面有注释,这里就不往里面分析了。

*/

 

/******************************************************************************

*   CamAdapter::startPreview() ->IState::onStartPreview() ->

*   IStateHandler::onHandleStartPreview() ->CamAdapter::onHandleStartPreview()

*******************************************************************************/

status_t

CamAdapter::

onHandleStartPreview()

{

   CAM_TRACE_NAME("Adapter::onHandleStartPreview");

   MY_LOGD("+");

 

   CPTLog(Event_Hal_Adapter_MtkDefaultPreview_start, CPTFlagStart);

 

   //

   int32_t eResourceType = ( getParamsManager()->getRecordingHint() )

                ? ResourceLock::eMTKVIDEO_PRV :ResourceLock::eMTKPHOTO_PRV;

   //

   if ( !mpResourceLock->SetMode((ResourceLock::ECamAdapter)eResourceType) )

    {

       CAM_LOGE("Resource SetMode fail");

       return INVALID_OPERATION;

    }

 

   //

   if ( ! mpResourceLock->Lock((ResourceLock::ECamAdapter)eResourceType))

    {

       CAM_LOGE("Resource Lock fail");

       return INVALID_OPERATION;

    }

   

   //

   CPTLog(Event_Hal_Adapter_MtkDefaultPreview_start_init, CPTFlagStart);

   if ( ! mpPreviewCmdQueThread->postCommand(PrvCmdCookie::eStart, PrvCmdCookie::eSemAfter) )

    {

       MY_LOGE("StartPreview stage 1 (start): fail");

       goto lbExit;

    }

   CPTLog(Event_Hal_Adapter_MtkDefaultPreview_start_init, CPTFlagEnd);

   

   //

   CPTLog(Event_Hal_Adapter_MtkDefaultPreview_start_stable, CPTFlagStart);

   if ( ! mpPreviewCmdQueThread->postCommand(PrvCmdCookie::eDelay, PrvCmdCookie::eSemAfter) )

    {

        MY_LOGE("StartPreview stage 2 (delay): fail");

        goto lbExit;

    }

   CPTLog(Event_Hal_Adapter_MtkDefaultPreview_start_stable, CPTFlagEnd);

   //

   if ( ! mpPreviewCmdQueThread->postCommand(PrvCmdCookie::eUpdate, PrvCmdCookie::eSemBefore) )

    {

        MY_LOGE("StartPreview stage 3 (udpate): fail");

        goto lbExit;

    }

   //

   CPTLog(Event_Hal_Adapter_MtkDefaultPreview_start, CPTFlagEnd);

 

   MY_LOGD("-");

   return OK;

   //

lbExit:

   return INVALID_OPERATION;

}

/*

mpPreviewCmdQueThread线程发了三个消息,eStartà eDelay-à eUpdate.下面我们进入mpPreviewCmdQueThread线程里面看看这三个消息的处理过程。

*/

Step 4.2.4:

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt8127\v1\hal\adapter\MtkDefault\Preview\PreviewCmdQueThread.cpp

 

bool

PreviewCmdQueThread::threadLoop()

{

   FUNCTION_IN;

   //

   bool ret = true;

   //

   sp pCmdCookie;

   //

   if (getCommand(pCmdCookie))

    {

       if(pCmdCookie != 0)

       {

           pCmdCookie->postSem(PrvCmdCookie::eSemBefore);

       }

       //

       bool isvalid = true;

       //

       switch (pCmdCookie->getCmd())

       {

/*

PrvCmdCookie::eDelay只是一个延时的处理,我们下面跟进下startupdate

*/

           casePrvCmdCookie::eStart:

                isvalid = start();

                break;

           casePrvCmdCookie::eDelay:

                isvalid =delay(EQueryType_Init);

                break;

           casePrvCmdCookie::eUpdate:

                isvalid = update();

                break;

           case PrvCmdCookie::ePrecap:

                isvalid = precap();

                break;

           case PrvCmdCookie::eStop:

                isvalid = stop();

                break;

           case PrvCmdCookie::eExit:

           default:

                break;

        }

 

       //

       if(pCmdCookie != 0)

       {

           pCmdCookie->setValid(isvalid);

           pCmdCookie->postSem(PrvCmdCookie::eSemAfter);

       }

    }

   //

   FUNCTION_OUT;

   //

   return ret;

}

 

Step  4.2.5:

 

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt8127\v1\hal\adapter\MtkDefault\Preview\PreviewCmdQueThread.cpp

 

bool

PreviewCmdQueThread::

start()

{

   CAM_TRACE_NAME("PrvCQT_DEF::start");

   FUNCTION_IN;

   //

   bool ret = false;

   vector vimgInfo;

   vector vBufPass1Out;

   ImgBufQueNode Pass1Node;

   IhwScenario::PortBufInfo BufInfo;

   //

   EIspProfile_T eIspProfile = ( mspParamsMgr->getRecordingHint() )

                ? EIspProfile_VideoPreview :EIspProfile_NormalPreview;

   ECmd_T eCmd = ( mspParamsMgr->getRecordingHint() )

                ? ECmd_CamcorderPreviewStart :ECmd_CameraPreviewStart;

   mbRecordingHint = ( mspParamsMgr->getRecordingHint() )

                ? true : false;

 

   //(0) scenario ID is decided by recording hint

   //

   int32_t eScenarioId = ( mspParamsMgr->getRecordingHint() )

                ?ACDK_SCENARIO_ID_VIDEO_PREVIEW : ACDK_SCENARIO_ID_CAMERA_PREVIEW;

 

   //(1) sensor (singleton)

   //

   CPTLogStr(Event_Hal_Adapter_MtkDefaultPreview_start_init,CPTFlagSeparator, "Init Sensor");

   //

   if ( ! (ret = mSensorInfo.init((ACDK_SCENARIO_ID_ENUM)eScenarioId)))

    {

       MY_LOGE("Init sensor fail!!");

       goto lbExit;

    }

 

 

   //(2) Hw scenario

   //

   CPTLogStr(Event_Hal_Adapter_MtkDefaultPreview_start_init,CPTFlagSeparator, "Init Hw");

   //

   mpHwScenario = IhwScenario::createInstance(eHW_VSS,mSensorInfo.getSensorType(),

                                               mSensorInfo.meSensorDev,

                                              mSensorInfo.mSensorBitOrder);

   if(mpHwScenario != NULL)

    {

       if(!(mpHwScenario->init()))

       {

           MY_LOGE("init Hw Scenario fail!!");

           goto lbExit;

       }

    }

   else

    {

       MY_LOGE("mpHwScenario is NULL!!");

       goto lbExit;

    }

 

   // (2.1) hw config

   //

   getCfg(eID_Pass1In|eID_Pass1Out, vimgInfo);

   getHw()->setConfig(&vimgInfo);

 

   // (2.2) enque pass 1 buffer

   //     must do this earlier thanhw start

   CAM_TRACE_BEGIN("PrvBufHdl::allocBuffer");

   mspPreviewBufHandler->allocBuffer(

                         mSensorInfo.getImgWidth(),

                         mSensorInfo.getImgHeight(),

                         mSensorInfo.getImgFormat(),

                         PASS1BUFCNT+PASS1BUFCNT_VSS);

   CAM_TRACE_END();

 

   for (int32_t i = 0; i < PASS1BUFCNT; i++)

    {

       mspPreviewBufHandler->dequeBuffer(eID_Pass1Out, Pass1Node);

       mapNode2BufInfo(eID_Pass1Out, Pass1Node, BufInfo);

       vBufPass1Out.push_back(BufInfo);

    }

   getHw()->enque(NULL, &vBufPass1Out);

   //

   #if VSS_ENABLE

   mspPreviewBufHandler->dequeBuffer(eID_Pass1Out, Pass1Node);

   mapNode2BufInfo(eID_Pass1Out, Pass1Node, BufInfo);

   mvBufPass1OutVss.clear();

   mvBufPass1OutVss.push_back(BufInfo);

   #endif

 

   //(3) 3A

   //!! must be set after hw->enque; otherwise, over-exposure.

   CPTLogStr(Event_Hal_Adapter_MtkDefaultPreview_start_init,CPTFlagSeparator, "Init 3A");

   //

   mp3AHal =Hal3ABase::createInstance(DevMetaInfo::queryHalSensorDev(gInfo.openId));

   if ( ! mp3AHal )

    {

       MY_LOGE("init 3A fail!!");

       goto lbExit;

    }

   CAM_TRACE_BEGIN("3A::setZoom");

    mp3AHal->setZoom(100,0, 0, mSensorInfo.getImgWidth(), mSensorInfo.getImgHeight());

   CAM_TRACE_END();

   CAM_TRACE_BEGIN("3A::setIspProfile");

   mp3AHal->setSensorMode(eScenarioId);

   mp3AHal->setIspProfile(eIspProfile);

   CAM_TRACE_END();

   CAM_TRACE_BEGIN("3A::sendCommand");

   mp3AHal->sendCommand(eCmd);

   CAM_TRACE_END();

   // (4) EIS

   //

   CPTLogStr(Event_Hal_Adapter_MtkDefaultPreview_start_init,CPTFlagSeparator, "Init EIS");

   mpEisHal = EisHalBase::createInstance("mtkdefaultAdapter");

   if(mpEisHal != NULL)

    {

       eisHal_config_t eisHalConfig;

       eisHalConfig.imageWidth = mSensorInfo.getImgWidth();

       eisHalConfig.imageHeight = mSensorInfo.getImgHeight();

       CAM_TRACE_BEGIN("EIS::configEIS");

        mpEisHal->configEIS(

                    eHW_VSS,

                    eisHalConfig);

       CAM_TRACE_END();

    }

   else

    {

       MY_LOGE("mpEisHal is NULL");

       goto lbExit;

    }

   //

   #if VSS_ENABLE

   mpVideoSnapshotScenario = IVideoSnapshotScenario::createInstance();

   #endif

   // (5) hw start

   //!!enable pass1 SHOULD BE last step!!

   CPTLogStr(Event_Hal_Adapter_MtkDefaultPreview_start_init,CPTFlagSeparator, "Hw start");

   //

   if ( ! getHw()->start())

    {

       goto lbExit;

    }

   //

   ret = true;

lbExit:

   //

   FUNCTION_OUT;

   //

   return ret;

}

 

/*

Startupdate获取到了sensor的数据,然后交给ISP进行了3AEIS等的处理,然后向外发出来。对于如何获取的sensor数据,ISP又是如何处理的,这里还是不明白。待学习。

最后是通过mspPreviewBufHandler->enqueBuffer(dispNode)向外传递BUFF的。我想如果有办法把各个阶段的BUFF保存起来看看,应该很不错。单不知道如何实现。

*/

官方有个数据流程图,供参考:

 

Step 4.2.6:

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt8127\v1\hal\adapter\MtkDefault\Preview\PreviewBufMgr.cpp

 

bool

PreviewBufMgr::

enqueBuffer(ImgBufQueNode const& node)

{

   // (1) set DONE tag into package

   const_cast(&node)->setStatus(ImgBufQueNode::eSTATUS_DONE);

 

   // (2) choose the correct "client"

   switch (node.getCookieDE())

    {

       case eBuf_Pass1:

       {

           if (mspHwBufPvdr != 0)

           {

               mspHwBufPvdr->enque(node.getImgBuf());

           }

       }

       break;

       //

       case eBuf_Disp:

       {

           sp bufProvider =mspImgBufProvidersMgr->getDisplayPvdr();

           if (bufProvider != 0)

           {

               bufProvider->enqueProvider(node);

           }

       }

       break;

       //

       case eBuf_AP:

       {

           sp bufProvider;

           {

                bufProvider =mspImgBufProvidersMgr->getPrvCBPvdr();

                if ( bufProvider != 0 )

                {

                   const_cast(&node)->setCookieDE(0); // 0 forpreview

                    bufProvider->enqueProvider(node);

                }

 

                // If fd exists, copy to it

                bufProvider =mspImgBufProvidersMgr->getFDBufPvdr();

                ImgBufQueNode FDnode;

                if (bufProvider != 0 &&bufProvider->dequeProvider(FDnode))

                {

                    if (FDnode.getImgBuf()->getBufSize() >= node.getImgBuf()->getBufSize())

                    {

                       memcpy(FDnode.getImgBuf()->getVirAddr(),

                          node.getImgBuf()->getVirAddr(),

                          node.getImgBuf()->getBufSize());

                       const_cast(&FDnode)->setStatus(ImgBufQueNode::eSTATUS_DONE);

                    }

                    else

                    {

                        MY_LOGE("fd buffer size < apbuffer size");

                       const_cast(&FDnode)->setStatus(ImgBufQueNode::eSTATUS_CANCEL);

                    }

                    //

                    bufProvider->enqueProvider(FDnode);                   

                }

           }

       }

       break;       

       //

       case eBuf_FD:

       {

           sp bufProvider =mspImgBufProvidersMgr->getFDBufPvdr();

           if (bufProvider != 0)

           {

               bufProvider->enqueProvider(node);

           }

       }

       break;

       //

       case eBuf_Rec:

       {

           sp bufProvider =mspImgBufProvidersMgr->getRecCBPvdr();

           if (bufProvider != 0)

           {

                bufProvider->enqueProvider(node);

           }

       }

       break;

       //

       default:

           MY_LOGE("unknown port(%d)!!", node.getCookieDE());

       break;

    }

   

   return true;

}

 

/*

到这里为止,数据已经获取到了,放到了这个bufProvider= mspImgBufProvidersMgr里面,上面是如何传递和使用的,待下篇分析。

*/

你可能感兴趣的:(CAMERA学习)