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); //设置
        
 
posted @ 2020-11-25 14:47  luoyuna  阅读(1386)  评论(0编辑  收藏  举报