camera打開流程(preview)(APP->hal)


Cam1DeviceBase.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)
Cam1DeviceBase:: onCam1Device_NotifyCb

接上章的 mpCamClient->startPreview() //開始使能Preview

 
Camera.java (packages\apps\legacycamera\src\com\android\camera)
onCreate
    mCameraPreviewThread.start(); //執行
Thread里面的run函數
 
Thread mCameraPreviewThread = new Thread(new Runnable() {
        public void run() {
            initializeCapabilities();   //單獨分析1
            startPreview();    //單獨分析2
        }
    });
 
 
 
initializeCapabilities  //單獨分析1
     //獲取攝像頭的一些參數,private android.hardware.Camera mCameraDevice;,所以這里會直接調用jni
    mInitialParams = mCameraDevice.getParameters();  
        //Camera.java (frameworks\base\core\java\android\hardware)
        Parameters p = new Parameters();
        String s = native_getParameters();
            //android_hardware_Camera.cpp (frameworks\base\core\jni)
             { "native_getParameters", "()Ljava/lang/String;", (void *)android_hardware_Camera_getParameters },
                sp<Camera> camera = get_native_camera(env, thiz, NULL);
                    sp<Camera> camera = get_native_camera(env, thiz, NULL); //得到Camera的引用,Camera.cpp (frameworks\av\camera)
                String8 params8 = camera->getParameters(); //這里通過引用調用Camera.cpp里面相應的函數
                    //在Camera.cpp (frameworks\av\camera)
                    params = mCamera->getParameters(); //這里的mCamera就是open攝像頭的時候得到camera的引用
                        //調用這里ICamera.cpp (frameworks\av\camera)
                        remote()->transact(GET_PARAMETERS, data, &reply); //通過binder從服務器端獲取,單獨分析3
    mFocusManager.initializeParameters(mInitialParams); 
 
 
 //開始預覽,單獨分析2
 startPreview();  
     setPreviewDisplay(mSurfaceHolder); //設置預覽的畫布
    setDisplayOrientation(); //設置顯示方向
        mDisplayRotation = Util.getDisplayRotation(this);  //獲得屏幕旋轉值
        mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId); //獲得屏幕方向
        mCameraDevice.setDisplayOrientation(mDisplayOrientation); //設置攝像頭的屏幕方向
        mFaceView.setDisplayOrientation(mDisplayOrientation); //設置面對面的方向
    setCameraParameters(UPDATE_PARAM_ALL); //設置攝像頭參數
        mParameters = mCameraDevice.getParameters(); //獲取參數,單獨分析1
        updateCameraParametersInitialize();  //更新參數
        mParameters.setPreviewFrameRate(max);
      // Inform the mainthread to go on the UI initialization.
    mCameraPreviewThread.notify(); //啟動主線程進行UI初始化
    mCameraDevice.startPreview();
        //android_hardware_Camera.cpp (frameworks\base\core\jni)
        sp<Camera> camera = get_native_camera(env, thiz, NULL);
        camera->startPreview()
            //Camera.cpp (frameworks\av\camera)
            sp <ICamera> c = mCamera;
            return c->startPreview(); //這里和get_parameters一個路徑, 單獨分析5
             
                
        
    
 
單獨分析3:獲取參數的服務端分析
    CameraHardwareInterface.h (frameworks\av\services\camera\libcameraservice\device1)
        char *temp = mDevice->ops->get_parameters(mDevice); //這里會調用到Cam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)的函數
            //Cam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)mtk_camera_device_ops數組中的get_parameters,加個一個前綴camera_get_parameters
            camera_get_parameters
                Cam1Device*const pDev = Cam1Device::getDevice(device); //獲取設備
                param = pDev->getParameters();  //調用 Cam1DeviceBase.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)
                String8 params_str8 = mpParamsMgr->flatten(); //獲取參數 ,mutable MtkCameraParameters         mParameters;
                    //ParamsManager.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\paramsmgr\params)的flatten
                        mParameters.flatten(); //調用這個來獲得參數
                            CameraParameters.cpp (frameworks\av\camera)  //獲取參數鍵值對,賦值給字符串,返回
                            size_t size = mMap.size();   //map的值的來源,單獨分析4
                            k = mMap.keyAt(i);
                            v = mMap.valueAt(i);
                strcpy(params_string, params_str8.string()); //把獲得的參數拷貝到params_string
 
            
單獨分析4: map的值的來源
ParamsManager.update.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\common\paramsmgr\params)
updateDefaultParams1_ByDefaultS函數中設置默認的參數值,
    mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "5000,30000");
updatePreviewFpsParams 函數中設置設置的參數值
    / /s8FpsRangeDefault.string());這個值從config.ftbl.common_raw.h得到,具體分析看config.ftbl.common_raw.h分析這章
   mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, s8FpsRangeDefault.string()); /
        // CameraParameters.cpp (frameworks\av\camera)中
        mMap.replaceValueFor(String8(key), String8(value));
 
 
單獨分析5:開始預覽 的服務端分析
     CameraHardwareInterface.h (frameworks\av\services\camera\libcameraservice\device1)
startPreview
     return mDevice->ops->start_preview(mDevice);
        //Cam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)mtk_camera_device_ops數組中的get_parameters,加個一個前綴camera_get_parameters
        camera_start_preview
            Cam1Device*const pDev = Cam1Device::getDevice(device);
            err = pDev->startPreview();
            //Cam1DeviceBase.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)
                if  ( mpCamAdapter != 0 && mpCamAdapter->isTakingPicture() ) //判讀是不是在拍照中
                    //MtkDefaultCamAdapter.Capture.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault)
                    isTakingPicture
                    //IState::eState_PreCapture,IState::eState_Capture, IState::eState_PreviewCapture, IState::eState_VideoSnapshot,如果是這些狀態就返回
                if  ( previewEnabled() ) //判斷是否使能了preview,如果已經使能了,就返回
                if  ( ! onStartPreview() ) //開始預覽,單獨分析6
             enableDisplayClient()   //使能顯示客戶端,單獨分析7
            mpCamClient->startPreview() //客戶端開始使能預覽,單獨分析10
            // forward to registered clients
            Vector<sp<ICamClient> >::const_iterator it;
            for (it = vmpCamClient.begin(); it != vmpCamClient.end(); ++it)
                (*it)->startPreview();
            //  startPreview in Camera Adapter.
            status = mpCamAdapter->startPreview();
                MtkDefaultCamAdapter.Preview.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault)
                mpStateManager->getCurrentState()->onStartPreview(this);
                    //StateManager.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault\state)
                    return mpCurrState;
                    State.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault\state)
                    onStartPreview
                        IStateManager::StateObserver stateWaiter(getStateManager());
                        getStateManager()->registerOneShotObserver(&stateWaiter);
                        status = pHandler->onHandleStopPreview();
                           // MtkDefaultCamAdapter.Preview.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault)
                            return forceStopAndCleanPreview();
            enableMsgType(CAMERA_MSG_PREVIEW_METADATA); //Enable a message, or set of messages.
 
               
                    
 
單獨分析6: 開始預覽
 if  ( ! onStartPreview() ) //開始預覽,單獨分析6
      //DefaultCam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\device)
                    (0) wait for thread
                    waitThreadInitDone() //等待初始化線程完成
                    //  (1) Check Permission.
                    pCamMgr->getPermission()  //檢查權限
                    // (2) Update Hal App Mode.
                    //ParamsManager.update.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\paramsmgr\params)
                    evaluateHalAppMode(s8HalAppMode)
                        return evaluateHalAppModeUtility(mode);
                            i4CamMode = mParameters.getInt(MtkCameraParameters::KEY_CAMERA_MODE); //獲取模式,現在應該是CAMERA_MODE_MTK_PRV
                            pszZsdMode = mParameters.get(MtkCameraParameters::KEY_ZSD_MODE //獲取是否是ZSD模式,如果是就
                            mode = MtkCameraParameters::APP_MODE_NAME_MTK_ZSD;
                    (3) Initialize Camera Adapter.
                    initCameraAdapter()
                        //  (1) Check to see if CamAdapter has existed or not. //如果不存在就創建一個
                        //  (2) Create & init a new CamAdapter.
                        mpCamAdapter = ICamAdapter::createInstance(mDevName, mi4OpenId, mpParamsMgr); //創建一個mpCamAdapter 
                            //BaseCamAdapter.Instance.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter)
                            s8AppMode = PARAMSMANAGER_MAP_INST(eMapAppMode)->stringFor(pParamsMgr->getHalAppMode()); //獲得APP的模式
                            if  ( s8AppMode == MtkCameraParameters::APP_MODE_NAME_MTK_PHOTO )  //根據不同模式,生成不同的Adapter,這里以預覽為例,后面又表格會說明什么情況生成什么Adapter
                                return  createMtkDefaultCamAdapter(s8AppMode, i4OpenId, pParamsMgr);  //單獨分析7,生成Adapter,下章分析
 
                                
 
 
 
單獨分析7: 使能顯示客戶端
 enableDisplayClient() 
                    [1] Get preview size.
                queryPreviewSize(previewSize.width, previewSize.height)  //獲取預覽大小
                    mpParamsMgr->getPreviewSize(&ri4Width, &ri4Height);
                            mParameters.getPreviewSize(width, height); 
                //  [2] Enable
                mpDisplayClient->enableDisplay(previewSize.width, previewSize.height, queryDisplayBufCount(), mpCamAdapter)
                    DisplayClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
                    preview_stream_ops* pStreamOps = mpStreamOps; //獲取數據流的操作函數
                    //  [.1] uninitialize  //先清除
                    uninit();
                       disableDisplay();
                       destroyDisplayThread();
                       destroyImgBufQueue();
                    //  [.2] initialize
                    init()  //初始化
                        createDisplayThread
                            ret =   createDisplayThread() 
                               //DisplayClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
                               return  new DisplayThread(pHandler);
                                    DisplayThread::DisplayThread(IDisplayThreadHandler*const pHandler) : IDisplayThread()
       , mpThreadHandler(pHandler)   //線程執行函數
        , mi4Tid(0)
       , miLogLevel(1)
       , mCmdQue()  //數據流的操作命令
       , mCmdQueMtx()
       , mCmdQueCond()
mpDisplayThread->run()  //運行線程,關注threadLoop,會響應命令
    threadLoop 
        case Command::eID_WAKEUP:
        mpThreadHandler->onThreadLoop(cmd);  //單獨分析8,onThreadLoop
                         createImgBufQueue()
                            mpImgBufQueue = new ImgBufQueue(IImgBufProvider::eID_DISPLAY, "CameraDisplay@ImgBufQue");  //創建緩存隊列
                            mpExtImgProc = ExtImgProc::createInstance();
                //  [.3] set related window info.
                    setWindow(pStreamOps, i4Width, i4Height, i4BufCount)  //后續分析
                        set_preview_stream_ops(window, wndWidth, wndHeight, i4MaxImgBufCount);
                //  [.4] set Image Buffer Provider Client.
             //  [2] Enable.
                   enableDisplay() //使能輸出
                       //  (2) Check to see if it has been enabled.
                       isDisplayEnabled()
                       //  (3) Check to see if thread is alive.
                       if  ( mpDisplayThread == 0 )
                       //  (4) Enable the flag.
                           ::android_atomic_write(1, &mIsDisplayEnabled);
                       //  (5) Post a command to wake up the thread.
                       mpDisplayThread->postCommand(Command(Command::eID_WAKEUP)); //這就是執行 onThreadLoop      單獨分析8
 
 
 //單獨分析8,onThreadLoop
    //DisplayClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
    //  (1) Prepare all TODO buffers.
    prepareAllTodoBuffers(pImgBufQueue)  //准備buf,單獨分析9
    //  (2) Start
    pImgBufQueue->startProcessor()
        //ImgBufQueue.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\camutils)
        mbIsProcessorRunning = true;
       mDoneImgBufQueCond.broadcast(); //發送廣播開始運行
    //  (3) Do until disabled.
        //  (.1)
        waitAndHandleReturnBuffers(pImgBufQueue);
           //  (1) deque buffers from processor.
            rpBufQueue->dequeProcessor(vQueNode);
            //  (2) handle buffers dequed from processor.
            ret = handleReturnBuffers(vQueNode);  //獲得返回的BUf
                /*
     * Notes:
     *  For 30 fps, we just enque (display) the latest frame,
     *  and cancel the others.
     *  For frame rate > 30 fps, we should judge the timestamp here or source.
     */
    //  (1) determine the latest DONE buffer index to display; otherwise CANCEL.
    if  ( rvQueNode[idxToDisp].isDONE() )  //如果是30幀的數據
        break; //跳出
    //  (3) Remove from List and enquePrvOps/cancelPrvOps, one by one.
        //  (.1)  Check valid pointers to image buffers in Queue & List
        if  ( rpQueImgBuf == 0 || pStreamImgBuf == 0 )
            continue;
        //  (.2)  Check the equality of image buffers between Queue & List.
        if  ( rpQueImgBuf->getVirAddr() != pStreamImgBuf->getVirAddr() )
            continue;
        //  (.3)  Every check is ok. Now remove the node from the list.
            mStreamBufList.erase(mStreamBufList.begin());
        //  (.4)  enquePrvOps/cancelPrvOps
            IExtImgProc::ImgInfo img; //賦值圖片的信息
            img.bufType     = ExtImgProc::BufType_Display;
            img.format      = pStreamImgBuf->getImgFormat();
            mpExtImgProc->doImgProc(img);
            // For Display Rotation
            if(rvQueNode[i].getOrientation() != 0)
                pStreamImgBuf->setNeedDisplayRotation(true);  //旋轉
            enquePrvOps(pStreamImgBuf); //放入buf
                  
 
 
單獨分析9: 准備buf
       prepareOneTodoBuffer(rpBufQueue)
            //  (2) deque it from PrvOps
            sp<StreamImgBuf> pStreamImgBuf;
            dequePrvOps(pStreamImgBuf)
            //DisplayClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
                //  [1] dequeue_buffer
                mpStreamOps->dequeue_buffer(mpStreamOps, &phBuffer, &stride);
                //  [3] Now let the graphics framework to lock the buffer, and provide us with the framebuffer data address.
                GraphicBufferMapper::get().lock(*phBuffer, CAMERA_GRALLOC_USAGE, bounds, &address);
                //  [4] Get the ion fd of gralloc buffer.
                err = ::gralloc_extra_query(*phBuffer, GRALLOC_EXTRA_GET_ION_FD, &fdIon);
                //  [5] Setup the output to return.
                rpImgBuf = new StreamImgBuf(mpStreamImgInfo, stride, address, phBuffer, fdIon);
        void* virtAddr = pStreamImgBuf->getVirAddr(); //得到虛擬地址
        if(pStreamImgBuf->getOrientation() & HAL_TRANSFORM_ROT_90) //如果是旋轉90
            pStreamImgBuf->setNeedDisplayRotation(true);
            memset((void*)virtAddr, iFirstFrameColor, pStreamImgBuf->getBufSize());
        enquePrvOps(pStreamImgBuf); //放入bug
            //  [3] set timestamp.
            err = mpStreamOps->set_timestamp(mpStreamOps, rpImgBuf->getTimestamp());
            //  [5] unlocks and post the buffer to display.
            err = mpStreamOps->enqueue_buffer(mpStreamOps, rpImgBuf->getBufHndlPtr());
        //  (3) enque it into Processor
        ret = rpBufQueue->enqueProcessor(
            ImgBufQueNode(pStreamImgBuf, ImgBufQueNode::eSTATUS_TODO, 0, 0, 0, (uint32_t)mi4Orientation)
        );
         //  (4) enque it into List & increment the list size.
        mStreamBufList.push_back(pStreamImgBuf);
 
 
單獨分析10, //客戶端開始使能預覽
mpCamClient->startPreview()
    mpFDClient->startPreview(); //啟動人臉檢測預覽,沒有什么工作
       //FDClient.h (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\client\camclient\fd)
        return true;
    mpPreviewClient->startPreview()
        PreviewClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
        :android_atomic_write(1, &mIsPrvStarted);
        ms8PrvTgtFmt = mpParamsMgr->getPreviewFormat(); //獲取格式
            //ParamsManager.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\paramsmgr\params)
            getStr(CameraParameters::KEY_PREVIEW_FORMAT);
        mpParamsMgr->getPreviewSize(&mi4PrvWidth, &mi4PrvHeight); //得到預覽尺寸
            mParameters.getPreviewSize(width, height);
        initBuffers();
            //PreviewClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
            //分配buf
            mpImgBufMgr = ImgBufManager::alloc(ms8PrvTgtFmt,  mi4PrvWidth, mi4PrvHeight, eMAX_PREVIEW_BUFFER_NUM, "PreviewClientCb", mpCamMsgCbInfo->mRequestMemory,  0,  0);
            mpExtImgProc = ExtImgProc::createInstance(); //創建IMG信息結構體,
                // ExtImgProcImp.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\extimgproc)
                return ExtImgProcImp::getInstance();
                    static ExtImgProcImp Singleton;
                        //Set which img buf you want to process.
      //For example: mImgMask = BufType_Display|BufType_Record;
       mImgMask = 0; //這里表示哪種BUF
       mUser = 0;  //user的個數
     mpExtImgProc->init();
         // ExtImgProcImp.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\extimgproc)
           android_atomic_inc(&mUser);  //用戶加一

            onStateChanged();

                ////  enable if both preview started && message enabled; otherwise disable.
                if  ( isEnabledState() ) 
                    0 != ::android_atomic_release_load(&mIsMsgEnabled) &&  0 != ::android_atomic_release_load(&mIsPrvStarted)
                postCommand(Command(Command::eID_WAKEUP)); //啟動線程PreviewClient.Thread.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
                    threadLoop()
                        case Command::eID_WAKEUP:
                            onClientThreadLoop //單獨分析11
 
 
//單獨分析11: onClientThreadLoop
onClientThreadLoop 
    //  (1) Get references to pool/queue before starting, so that nothing will be free during operations.
    //  (2) stop & clear all buffers so that we won't deque any undefined buffer.
    pBufQueue->stopProcessor();
    //  (3) Prepare all TODO buffers.
    prepareAllTodoBuffers(pBufQueue, pBufMgr)
        //PreviewClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
        //  For better performance, we should enque all TODO buffers before starting.//  In that case, we could deque more than one buffers, and should enque //  them in the loop.
        //  (1) Determine how many buffers to enque.
        //  all buffers = callback buffers + enq buffers (in list) + not-enq buffers (others)
        //  Assumption:
        //  (1) callback is returned in order.
        //  (2) all callback are returned within this function,
        //      ==> not-enq buffers (others) = eMAX_PREVIEW_BUFFER_NUM - mImgBufList.size()
        iEnqCount = eMAX_PREVIEW_BUFFER_NUM - mImgBufList.size();
             //  (.1) Determine which buffer to enque.
            pCameraImgBuf = rpBufMgr->getBuf(muImgBufIdx);
            muImgBufIdx = (muImgBufIdx+1) % eMAX_PREVIEW_BUFFER_NUM;
            //  (.2) enque it into Processor
            ret = rpBufQueue->enqueProcessor( ImgBufQueNode(pCameraImgBuf, ImgBufQueNode::eSTATUS_TODO));
            //  (.3) enque it into List & increment the list size.
            mImgBufList.push_back(pCameraImgBuf);
    //  (4) Start
    pBufQueue->startProcessor()
    //  (5)   Do until all wanted messages are disabled.
    ::android_atomic_write(1, &mIsWaitBufBack);
        //  (.1)
        waitAndHandleReturnBuffers(pBufQueue); //等待BUF完成
            //PreviewClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
            //  (1) deque buffers from processor.
           rpBufQueue->dequeProcessor(vQueNode);
            //  (2) handle buffers dequed from processor.
           ret = handleReturnBuffers(vQueNode); //這個和//單獨分析8,onThreadLoop一樣
   mpRecordClient->startPreview()
        RecordClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\record)
        if(mpParamsMgr->getInt(CameraParameters::KEY_PREVIEW_FRAME_RATE) > 30)
            mRecBufNum = 5 + (mpParamsMgr->getInt(CameraParameters::KEY_PREVIEW_FRAME_RATE)/30)*2 + 2; //獲得buf的數量
        mpParamsMgr->set(MtkCameraParameters::KEY_VR_BUFFER_COUNT, mRecBufNum); //設置
        
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM