學習Android camera筆記 & 調用流程


參考:http://blog.csdn.net/xingyu19871124/article/details/7750189
     http://blog.csdn.net/BonderWu/article/details/5814278
     http://blog.chinaunix.net/uid-2630593-id-3307176.html
     http://zhidao.baidu.com/question/388864295.html
     等

注:把本文內容復制到source insight中查看效果較好

    
    
     線程與進程:子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器為其執行上下文。
    
     Handler與線程:  其實Handler並不是開辟新線程的概念,Android主要的考慮到更新界面的問題,一般情況下,更新界面(Activity)都是在主線程中更新的,
     這樣就遇到了一個問題,比方說:在下載文件時候我們需要進度條顯示下載進度,界面需要更新(數據是不斷變的,也就是下載的大小是不斷變的,要是直接
     在主線程中更新,就會造成程序的堵塞,程序很容易崩潰,通常這樣聯網耗時的工作需要開辟另外一個線程的,這樣就不會影響主程序了),好了,到這里聯
     網操作一般都需要開辟新線程了吧。
     接下來就來說Handler了,剛剛我說了Handler不是開辟新線程,在我看來,Handler更像是主線程的秘書,是一個觸發器,負責管理從子線程中得到更新的數據,
     然后在主線程中更新界面。簡單說下進度條的那個:  下載了多少的數據都是在子線程中得到的,在子線程中通過Handler的sendMessage()方法發送得到的下載
     的數據,當你調用了sendMessage方法后,Handler就會回調(也就是自動調用)Handler中的 HandlerMessage方法。

     啟動線程:Android啟動線程和JAVA一樣有兩種方式,一種是直接Thread類的start方法,也就是一般寫一個自己的類來繼承Thread    類。
     另外一種方式其實和這個差不多啊! 那就是Runnable接口,然后把Runnable的子類對象傳遞給Thread類再創建Thread對象.總之都是需要創建Thread對象,
     然后調用Thread類的start方法啟動線程。區別就是,一個是直接創建Thread對象,另外一個是需要implement了Runnable接口對象作為創建Thread對象的參數.    
     Runnable其實我們稱為線程任務。
      第一種方式一般是這樣用:
        Class MyThread extends Thread{
              public void run(){
               //你要實現的代碼
             }
        }
         在主線程中啟動這個線程:
        public class Test{
            public static void main(String[] args){
                new MyThread().start();//啟動了我們的線程了
            }
        }
        2,第二種方式一般是這樣用:
        public class MyRunnable implements Runnable{
            public void run(){
                //你需要實現的代碼
            }
        }
        在主線程中啟動這個線程:
        public class Test{
            public static void main(String[] args){
                 Thread t=new Thread(new MyRunnable());//這里比第一種創建線程對象多了個任務對象
                 t.start();
            }
        }
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
cpp:
LOGD("dyyr - log %s, %s", __FILE__, __FUNCTION__);


打開camera/喚醒camera    大致流程途徑源文件:

    Camera.java            onCreate()     log1
                        開啟一個新線程,在此線程中open camera

                        mCameraOpenThread的run()
                                    log2
                        運行構造函數中的run()
                        是上述兩種開啟線程方法中的第一種

                        Then do something about rotation and else.
                        在onCreate()中以mCameraOpenThread.join();這句等待該線程完成它的任務
                        再開啟預覽線程mCameraPreviewThread.start();

                        mCameraPreviewThread的run()
                1872                    log14

                        startPreview()
                                    log14.5
                                    mCameraDevice是在log4的位置定義的,是log5返回的一個android.hardware.Camera對象
                                    (因為log5源文件第一句:package android.hardware;)
                                    這個對象的startPreview方法聲明在log5下面。481行
                                    而它在log15定義。

                                    

                                    
    Util.java            openCamera() log3            

    CameraHolder.java        open()         log4
                                                
                                                Applications
---------------------------------------------------------------------------------------------------------------------------
    Camera.java            open()         log5
    
                                                   Framework
---------------------------------------------------------------------------------------------------------------------------
    android_hardware_camera.cpp    
        android_hardware_Camera_native_setup()
                                    log6

        android_hardware_Camera_startPreview()
                                    log15

    Camera.cpp        connect()         log7

                    startPreview()    log16

    CameraService.cpp connect()         log8        IServiceManager.cpp        ServiceManager.java(comfirmed)
                                    log8.1
                                    log8.2

                    Client()            log8.3~8.8
                        怎么到下面的log9?
                    
                    startPreview()    log17
                    startCameraMode() log18
                    startPreviewMode()log19
                                                         JNI
---------------------------------------------------------------------------------------------------------------------------
                                                             進入camera之前(開機時),camera初始化
                                                              CameraHardwareDevice.cpp         Initialize()   log'1
ALCameraFactory.cpp device_open()       log9 (name=0)          V4L2CameraDevice.cpp            Initialize()   log'2
                  cameraDeviceOpen()  log10

CameraHardware.cpp  connectCamera()        log11                  V4L2Camera.cpp                Initialize()   log'3

                    startPreview()    log20
                    doStartPreview()    log21

V4L2CameraDevice.cpp  connectDevice()    log12                  V4L2Camera.h                    WorkerThread()  log'4  上述兩種開啟線程方法中的第一種,但並沒有run(),
                                                                                                        所以還沒有真正開啟線程,初始化了一個指針V4L2Camera* camera_dev
                    openCameraDev()    log13
在這個最終打開設備文件的函數中,open()得到文件描述符后,
用iotrl()函數做了一些配置然后返回了

PreviewWindow.cpp        startPreview()    log22
                    onNextFrameAvailableHW()    log23
                    通過perform向mPreviewWindow窗體發送消息

                    打開camera並開啟預覽的流程跟到這里。

camera.cfg
                                                         HAL
---------------------------------------------------------------------------------------------------------------------------
    gc0308.c
    Sys_config1.fex
                                                      Kernel
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
cpp:
LOGD("dyyr - log %s, %s", __FILE__, __FUNCTION__);


Camera.java    

    1117        public void onCreate(Bundle icicle) {            //打開

                ......

                mCameraOpenThread.start();                                //  1097

                ......

            }


    1097        Thread mCameraOpenThread = new Thread(new Runnable() {
                public void run() {
                    try {
                        mCameraDevice = Util.openCamera(Camera.this, mCameraId);        //Util.java    267
                    }

                    .......

                }
             }
             
    1532        protected void doOnResume() {                //喚醒

                ......
                
                Util.openCamera(this, mCameraId);                        //Util.java    267

                ......

            }



    1836        private void startPreview() {

                ......

                
                if (mCameraPreviewThread != null) {
                        synchronized (mCameraPreviewThread) {
                            mCameraPreviewThread.notify();                      //開啟預覽線程
                        }
                    }

                    ......

                    
            }


Util.java                        package/apps/.../camera

    267        CameraHolder.instance().open(cameraId);                




CameraHolder.java                    package/apps/.../camera

    131        android.hardware.Camera.open(cameraId);            //無法自動定位,frameworks/base/core/java/android/hardware/Camera.java        264    open()
    




                            packages/apps/camera/src/com/android/camera/         -------->    Camera.apk






                                                                                                    Applications
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



Camera.java     frameworks/base/core/java/android/hardware/Camera.java                  -------->   framework.jar

    264        public static Camera open(int cameraId) {
                return new Camera(cameraId);
            }                                        //open函數是一個靜態方法,構造一個Camera對象

    285        Camera(int cameraId) {                    //構造函數
            mShutterCallback = null;
            mRawImageCallback = null;
            mJpegCallback = null;
            mPreviewCallback = null;
            mPostviewCallback = null;
            mZoomListener = null;

            Looper looper;
            if ((looper = Looper.myLooper()) != null) {
                mEventHandler = new EventHandler(this, looper);
            } else if ((looper = Looper.getMainLooper()) != null) {
                mEventHandler = new EventHandler(this, looper);
            } else {
                mEventHandler = null;
            }

            native_setup(new WeakReference<Camera>(this), cameraId);                    //310
        }


    310        private native final void native_setup(Object camera_this, int cameraId);        其對應於android_hardware_Camera.cpp的android_hardware_Camera_native_setup方法,為什么????
                                                                                    貌似是有函數會去按照camMethods數組匹配



                                                                                                    Frameworks
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


android_hardware_camera.cpp            frameworks/base/core/jni

    458        // connect to camera service
            static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
                jobject weak_this, jint cameraId)
            {
                sp<Camera> camera = Camera::connect(cameraId);            //無法自動定位.  Camera.cpp 128
                                                                    //Camera C/S架構的客戶端調用connect函數向服務器發送連接請求,
                                                                    //這個Camera類的聲明在Camera.h (android4.0\frameworks\base\include\camera)

                if (camera == NULL) {
                    jniThrowRuntimeException(env, "Fail to connect to camera service");
                    return;
                }

                // make sure camera hardware is alive
                if (camera->getStatus() != NO_ERROR) {
                    jniThrowRuntimeException(env, "Camera initialization failed");
                    return;
                }

                jclass clazz = env->GetObjectClass(thiz);
                if (clazz == NULL) {
                    jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
                    return;
                }

                // We use a weak reference so the Camera object can be garbage collected.
                // The reference is only used as a proxy for callbacks.
                sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz
            , camera);

                context->incStrong(thiz);
                camera->setListener(context);

                // save context in opaque field
                env->SetIntField(thiz, fields.context, (int)context.get());
            }


Camera.cpp        frameworks/base/libs/camera

    128        sp<Camera> Camera::connect(int cameraId)
            {
                LOGV("connect");
                sp<Camera> c = new Camera();
                const sp<ICameraService>& cs = getCameraService();            //獲取一個Camera服務實例,本源文件40行
                if (cs != 0) {
                    c->mCamera = cs->connect(c, cameraId);                    //然后執行服務端的connect()函數,並返回一個ICamera對象賦值給Camera 的mCamera,
                                                                       //CameraService.cpp    185~254
                }
                if (c->mCamera != 0) {
                    c->mCamera->asBinder()->linkToDeath(c);
                    c->mStatus = NO_ERROR;
                } else {
                    c.clear();
                }
                return c;
            }

    
    40    // establish binder interface to camera service
        const sp<ICameraService>& Camera::getCameraService()
        {
            Mutex::Autolock _l(mLock);
            if (mCameraService.get() == 0) {
                sp<IServiceManager> sm = defaultServiceManager();                    //無法自動定位,調用的是IServiceManager.cpp(frameworks/base/libs/binder)    34
                sp<IBinder> binder;
                do {
                    binder = sm->getService(String16("media.camera"));            //無法自動定位,搜索符號getService,定位到ServiceManager.java   49
                    if (binder != 0)
                        break;
                    LOGW("CameraService not published, waiting...");
                    usleep(500000); // 0.5 s
                } while(true);
                if (mDeathNotifier == NULL) {
                    mDeathNotifier = new DeathNotifier();
                }
                binder->linkToDeath(mDeathNotifier);
                mCameraService = interface_cast<ICameraService>(binder);    //mCameraService是一個ICamerService類型,
                                                                        //更加具體具體一點來講應該是BpCameraService,因為在這個類中實現了ICameraService的方法。
            }
            LOGE_IF(mCameraService==0, "no CameraService!?");
            return mCameraService;
        }


IServiceManager.cpp        frameworks/base/libs/binder

    34        sp<IServiceManager> defaultServiceManager()
            {
                if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
                
                {
                    AutoMutex _l(gDefaultServiceManagerLock);
                    if (gDefaultServiceManager == NULL) {
                        gDefaultServiceManager = interface_cast<IServiceManager>(   //得到上面要的sm,它的類型是"sp<IServiceManager>",
                                                                                 //sp<T>是android的智能指針,它持有一個T類實例,並負責在必要時釋放此實例
                            ProcessState::self()->getContextObject(NULL));
                    }
                }
                
                return gDefaultServiceManager;
            }


我們有必要關注一下interface_cast,通過代碼跟蹤:看到它的實現
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
通過模板替換就是:
inline sp< IServiceManager > interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
看來asInterface是IServiceManager的一個成員函數,我們打開IServiceManager.cpp/
h文件,我們並沒有發現該函數,那它到底在哪兒呢,仔細觀察IServiceManager.cpp
,發現里面有個IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
在IServiceManager.h里面發現了DECLARE_META_INTERFACE(ServiceManager);
通過跟蹤這兩個宏發現DECLARE_META_INTERFACE聲明了一個變量和兩個函數...
interface_cast<IServiceManager>實際上返回了一個BpServiceManager,在創建一個BpServiceManager時,有些細節還是需要注意:...




ServiceManager.java        frameworks/base/core/java/android/os

    49    public static IBinder getService(String name) {
                Log.d(TAG, "dyyr - getService");
            try {
                IBinder service = sCache.get(name);          //sCache是個Hashmap<String,IBinder>,用參數name:"media.camera"get這個IBinder,
                                                            //那么,這個media.camera是源代碼里配置好的還是開機后添加進去的?何時添加的?
                if (service != null) {
                    return service;
                } else {
                    return getIServiceManager().getService(name);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "error in getService", e);
            }
            return null;
        }



CameraService.cpp            frameworks/base/services/camera/libcameraservice

    185        sp<ICamera> CameraService::connect(                                //服務端connect()
                    const sp<ICameraClient>& cameraClient, int cameraId) {
                LOGE("dyyr - CameraService.cpp connect");
                int callingPid = getCallingPid();
                sp<CameraHardwareInterface> hardware = NULL;                    //先實例化Camera Hal接口 hardware,
                    ......


    246            if (hardware->initialize(&mModule->common) != OK) {            //hardware調用initialize()進入HAL層打開Camear驅動, CameraHardwareDevice.cpp    52
                    hardware.clear();
                    return NULL;
                }

                client = new Client(this, cameraClient, hardware, cameraId, info.facing,
            callingPid);

                mClient[cameraId] = client;
                LOG1("CameraService::connect X");
                return client;                                            //返回的其實是它內部類client的一個實例。
            }
            


//Camera系統使用的是Server-Client機制,Service和Client位於不同的進程中,進程間使用Binder機制進行通信,
//Service端實際實現相機相關的操作,Client端通過Binder接口調用Service對應的操作。
//如下圖所示


android_hardware_camera.cpp            fremework/base/core/jni                        -------->    libandroid_runtime.so                
                                                                                                    
                                                                                                    |
                                                                                                    |
                                                                                              ------    | --------------------------
                                                                                             |     ---------         ---------      |
                                                                                             |    |  Client |        | Service |-----------Binder IPC---------            
                                                                                             |     ---------         ---------      |                          |     
                                                                                             |            libui.so                  |                          |
                                                                                              -----------------------------------                          |
                                                                                                                                                ------
                                                                                                                                                |
    Camera服務                                                                                                                                    |
CameraService.cpp等                 frameworks/base/camera/libcameraservice/            -------->     libcameraservice.so  <------------------------------------


        (    UI 庫               frameworks/base/libs/ui/camera                        -------->            libcamera_client.so        )






                                                                                            JNI
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


CameraHardwareDevice.cpp        device/softwinner/common/hardware/camera/

    52        status_t CameraHardwareDevice::Initialize()
            {
                F_LOG;

                // instance V4L2CameraDevice object
                mV4L2CameraDevice = new V4L2CameraDevice(this, mCameraID);
                if (mV4L2CameraDevice == NULL)
                {
                    LOGE("Failed to create V4L2Camera instance");
                    return NO_MEMORY;
                }
                
                status_t res = mV4L2CameraDevice->Initialize();            //V4L2CameraDevice.cpp     71

                ......

            }
                

V4L2CameraDevice.cpp        device/softwinner/common/hardware/camera/

    71        status_t V4L2CameraDevice::Initialize()
            {
                F_LOG;

                return V4L2Camera::Initialize();            //V4L2Camera.cpp        66
            }


V4L2Camera.cpp        device/softwinner/common/hardware/camera/

    66        status_t V4L2Camera::Initialize()
            {
                LOGE("dyyr - %s, %s", __FILE__, __FUNCTION__);
                F_LOG;
                if (isInitialized()) {
                    LOGW("%s: V4L2Camera device is already initialized: mState = %d",
                         __FUNCTION__, mState);
                    return NO_ERROR;
                }

                /* Instantiate worker thread object. */
                mWorkerThread = new WorkerThread(this);                                    //V4L2Camera.h    325
                if (getWorkerThread() == NULL) {
                    LOGE("%s: Unable to instantiate worker thread object", __FUNCTION__);
                    return ENOMEM;
                }

                mState = ECDS_INITIALIZED;

                return NO_ERROR;
            }


V4L2Camera.h        device/softwinner/common/hardware/camera/

    325        inline explicit WorkerThread(V4L2Camera* camera_dev)
                : Thread(true),   // Callbacks may involve Java calls.                //頂層打開/喚醒Camera的流程跟到這里---------------------------未完待續
                  mCameraDevice(camera_dev),
                  mThreadControl(-1),
                  mControlFD(-1)
            {
            }

------------------------------------------------------------------


下面是camera的HAL層open底層驅動的方法,沒有使用傳統的這一句:module->methods->open(module, mName.string(),(hw_device_t **)&mDevice),而走的是V4L2途徑:


HALCameraFactory.cpp        device/softwinner/common/hardware/camera/

    201        struct hw_module_methods_t HALCameraFactory::mCameraModuleMethods = {
                open: HALCameraFactory::device_open                                            //    160
            };


    160        int HALCameraFactory::device_open(const hw_module_t* module,
                                                   const char* name,
                                                   hw_device_t** device)
            {
                F_LOG;
                /*
                 * Simply verify the parameters, and dispatch the call inside the            //只需確定參數,並調用HALCamera 實例.
                 * HALCameraFactory instance.
                 */


                ......
                

                return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device);            //    118
            }


    118        int HALCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device)
            {
                LOGV("%s: id = %d", __FUNCTION__, camera_id);

                ......
                

                return mHardwareCameras[camera_id]->connectCamera(device);            //CameraHardware.cpp        435
            }



CameraHardware.cpp        device/softwinner/common/hardware/camera/

    435        status_t CameraHardware::connectCamera(hw_device_t** device)
            {

            
                ......


                if (camera_dev != NULL) {
                    /* Connect to the camera device. */
                    res = getCameraDevice()->connectDevice();                    //V4L2CameraDevice        83
                    if (res == NO_ERROR) {
                        *device = &common;
                    }
                }

                return -res;
            }



V4L2CameraDevice.cpp        device/softwinner/common/hardware/camera/

    83        status_t V4L2CameraDevice::connectDevice()
            {


                ......


                // open v4l2 camera device
                int ret = openCameraDev();                                                    //448
                if (ret != OK)
                {
                    return ret;
                }

                ret = cedarx_hardware_init(2);// CEDARX_HARDWARE_MODE_VIDEO

                ......

                
            }


    448        int V4L2CameraDevice::openCameraDev()
            {
                // open V4L2 device
                Log.d(TAG, "dyyr - " + __FILE__ + ", " + __FUNCTION__);
                mCamFd = open(mDeviceName, O_RDWR | O_NONBLOCK, 0);                            //至此完成打開底層設備全過程
                if (mCamFd == -1)
                {
                    LOGE("ERROR opening V4L interface: %s", strerror(errno));
                    return -1;
                }

                struct v4l2_input inp;
                inp.index = mDeviceID;
                if (-1 == ioctl (mCamFd, VIDIOC_S_INPUT, &inp))
                {
                    LOGE("VIDIOC_S_INPUT error!\n");
                    return -1;
                }

                ......


            }

--------------------------------------------------------------------------



HAL層的配置文件camera.cfg            device/softwinner/Dimond_97HD/camera.cfg,          讀取配置:  CCameraConfig.cpp,  xxx()

下面是讀取配置信息的一個例子:

CameraHardware.cpp            device/softwinner/common/hardware/camera/

    105        status_t CameraHardware::Initialize()
            {
                F_LOG;

                if (mCameraConfig == NULL)
                {
                    return UNKNOWN_ERROR;
                }

                initDefaultParameters();                //145

                return NO_ERROR;
            }


    145        void CameraHardware::initDefaultParameters()
            {
            

                ......


                if (mCameraConfig->cameraFacing() == CAMERA_FACING_BACK)                            //根據配置信息設置XX
                {
                    p.set(CameraHardware::FACING_KEY, CameraHardware::FACING_BACK);
                    LOGV("%s: camera is facing %s", __FUNCTION__, CameraHardware::FACING_BACK
            );

                }
                else
                {
                    p.set(CameraHardware::FACING_KEY, CameraHardware::FACING_FRONT);
                    LOGV("%s: camera is facing %s", __FUNCTION__, CameraHardware::
            FACING_FRONT);

                }
                
                p.set(CameraHardware::ORIENTATION_KEY, 0);


                ......


            }






                                                                                                    HAL
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



gc0308.c                        drivers/media/video/sun4i_csi/device/gc0308.c






配置文件Sys_config1.fex        Tools/pack/Chips/Sun4i/Configs/Crane/Dimod/Sys_config1.fex,  讀取函數:        ????????




                                                                                                    Kernel
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



免責聲明!

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



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