• Camera启动篇一


        主要记录一下启动的过程,顺便看看是否能把握到数据流的走向,这次以高通810平台Android5.1为蓝本。本篇主要讲述Framework及Hardware部分,涉及到JAVA及driver部分的如有必要也会捎带提及一下。

    一、启动Camera在JAVA层开始,主要是启动了一个OpenCameraThread的线程(PhotoModule.java),代码如下:

    1 if (mOpenCameraThread == null && !mActivity.mIsModuleSwitchInProgress) {
    2             mOpenCameraThread = new OpenCameraThread();
    3             mOpenCameraThread.start();
    4         }

        在这个线程中只做了两件事情,整个Camera的启动过程也是围绕着他们展开的:

    1     private class OpenCameraThread extends Thread {
    2         @Override
    3         public void run() {
    4             openCamera();      // 第一步开启camera
    5             startPreview();    // 第二部开始preview
    6         }
    7     }

    二、开启第一步openCamera

    1. 还是在Java层,openCamera主要干了下面这些事情:

            1.1 CameraUtility.openCamera  ------->重点部分

            1.2 getParameters    ------->一些参数获得

            1.3 initializeFocusManager   -------->Focus管理

            1.4 initializeCapabilities    -------->Camera选择的一些特性

            1.5 sendMSG--CAMERA_OPEN_DONE    -------->Open完成之后的处理

    2. 上面那么多,我们只需要关注第一点就可以了,现在继续往下查看。关于这部分网上也有不少资料,可自行查看,直接查看源代码也比较清晰。总之在Camera开启成功后Java层会获得一个mCameraDevice,这个其实就是Camera的一个代理--AndroidCameraProxyImpl,当然我们要关注的是前面开启的过程。

     1     public CameraManager.CameraProxy cameraOpen(
     2         Handler handler, int cameraId, CameraOpenErrorCallback callback) {
     3         mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0,
     4                 CameraOpenErrorCallbackForward.getNewInstance(
     5                         handler, callback)).sendToTarget();
     6         mCameraHandler.waitDone();
     7         if (mCamera != null) {
     8             return new AndroidCameraProxyImpl();  // ----->这个就是丢给前台的mCameraDevice
     9         } else {
    10             return null;
    11         }
    12     }

    3. OPEN_CAMERA的处理先使用传统的方式开启,如果不行再尝试新的open方式,这里开始就转到frameworks。frameworks基本没做什么东西,就是一个传话筒而已,很快就到了JNI。

     1         public void handleMessage(final Message msg) {
     2             try {
     3                 switch (msg.what) {
     4                     case OPEN_CAMERA:
     5                         try {
     6                             mCamera = android.hardware.Camera.openLegacy(msg.arg1,     // 这里的android.hardware.Camera就指向frameworksasecorejavaandroidhardwarecamera.java
     7                                     android.hardware.Camera.CAMERA_HAL_API_VERSION_1_0);  // 先使用传统的接口打开
     8                         } catch (RuntimeException e) {
     9                             /* Retry with open if openLegacy fails */
    10                             Log.v(TAG, "openLegacy failed. Using open instead");
    11                             mCamera = android.hardware.Camera.open(msg.arg1); //若出现异常再使用新的接口打开,这里提供两种方式也是方便硬件厂商做兼容及区别处理,到现在的AndroidM版本,Camera HAL已经有了3个版本了,但高通810目前还是使用HAL1
    12                         }

    4. openLegacy的JNI调用为native_setup。JNI调用将转到android_hardware_Camera.cpp文件,关于这部分网上也有很多资料。其实这里也没干什么事情,跟frameworks一样,都只是一个传递的作用,整个Camera框架真正有内涵的还是HAL以及driver部分,当然APP部分的各种呈现也很有内涵。

     1 return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName); 

            这里通过JNI到了C++层

     1 // connect to camera service
     2 static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
     3     jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
     4 {
        。。。。。。10     //ALOGV("native setup: halversion %d", halVersion);//native setup: halversion 256
    11     sp<Camera> camera;
    12     if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {  //CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2
    13         // Default path: hal version is don't care, do normal camera connect.
    14         camera = Camera::connect(cameraId, clientName,
    15                 Camera::USE_CALLING_UID);
    16     } else {
    17         jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
    18                 Camera::USE_CALLING_UID, camera);
    19         if (status != NO_ERROR) {
    20             return status;
    21         }

           调用到Camera的connectLegacy

     1 status_t Camera::connectLegacy(int cameraId, int halVersion,
     2         const String16& clientPackageName,
     3         int clientUid,
     4         sp<Camera>& camera)    // 需返回的Camera设备
     5 {
     6     ALOGV("connectLegacy: connect legacy camera device,halVersion %d", halVersion);
     7     sp<Camera> c = new Camera(cameraId);
     8     sp<ICameraClient> cl = c;      // 这个示例很重要,CameraService将包含此示例,用来执行回调调用到Client这边。
     9     status_t status = NO_ERROR;
    10     const sp<ICameraService>& cs = CameraBaseT::getCameraService();   // 获取CameraService
    11 
    12     if (cs != 0) {
    13         status = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,   // 调用CameraService的connectLegacy
    14                                         clientUid, /*out*/c->mCamera);
    15     }
    16     if (status == OK && c->mCamera != 0) {
    17         c->mCamera->asBinder()->linkToDeath(c);
    18         c->mStatus = NO_ERROR;
    19         camera = c;
    20     } else {
    21         ALOGW("An error occurred while connecting to camera: %d", cameraId);
    22         c.clear();
    23     }
    24     return status;
    25 }

            这部分有太多的资料阐述,毕竟还是Android通用代码,未涉及到硬件芯片厂商的差异性。简约一些,connect会获得一个CameraService,这个Service将进行HAL层设备的管理及交互。我们跳转到CameraService::connectLegacy可以看到在这个Service中包含了一个CameraClient,而上面说到的返回的Camera设备就是这个Client(源码:device = client;)。

     1 status_t CameraService::connectLegacy(
     2         const sp<ICameraClient>& cameraClient,
     3         int cameraId, int halVersion,
     4         const String16& clientPackageName,
     5         int clientUid,
     6         /*out*/
     7         sp<ICamera>& device) {// go here
     8 
     9  。。。。。。
    10 
    11     status_t status = validateConnect(cameraId, /*inout*/clientUid);
    12     if (status != OK) {
    13         return status;
    14     }
    15 
    16     sp<Client> client;
    17     {
    18         sp<BasicClient> clientTmp;
    19         Mutex::Autolock lock(mServiceLock);
    20         if (!canConnectUnsafe(cameraId, clientPackageName,
    21                               cameraClient->asBinder(),
    22                               /*out*/clientTmp)) {
    23             return -EBUSY;
    24         } else if (client.get() != NULL) {
    25             device = static_cast<Client*>(clientTmp.get());
    26             return OK;
    27         }
    28 
    29         status = connectHelperLocked(/*out*/client,   // 这个client就是上面调用中要返回的Camera设备device
    30                                      cameraClient,    // 传下来的ICameraClient实例
    31                                      cameraId,
    32                                      clientPackageName,
    33                                      clientUid,
    34                                      callingPid,
    35                                      halVersion,
    36                                      /*legacyMode*/true);
    37         if (status != OK) {
    38             return status;
    39         }
    40 
    41     }
    42     // important: release the mutex here so the client can call back
    43     //    into the service from its destructor (can be at the end of the call)
    44 
    45     device = client;   // 返回的Client设备
    46     return OK;
    47 }

            在connectHelperLocked中,将根据不同HAL版本实现不同的示例,目前有CameraClient和Camera2Client两种

     1           case CAMERA_DEVICE_API_VERSION_1_0:
     2             ALOGV("create a camera client.line %d",__LINE__);
     3             client = new CameraClient(this, cameraClient,      // 前面那个CameraClient是要实现的Client,第二个cameraClient就是上面传下来的ICameraClient实例
     4                     clientPackageName, cameraId,
     5                     facing, callingPid, clientUid, getpid(), legacyMode);
     6             break;
     7           case CAMERA_DEVICE_API_VERSION_2_0:
     8           case CAMERA_DEVICE_API_VERSION_2_1:
     9           case CAMERA_DEVICE_API_VERSION_3_0:
    10           case CAMERA_DEVICE_API_VERSION_3_1:
    11           case CAMERA_DEVICE_API_VERSION_3_2:
    12             ALOGI("create a camera2 client");
    13             client = new Camera2Client(this, cameraClient,
    14                     clientPackageName, cameraId,
    15                     facing, callingPid, clientUid, getpid(), legacyMode);
    16             break;

            上面获得Client后会调用connectFinishUnsafe(client, client->getRemote()),这个函数将会执行到HAL的interface,所以厂家通用。

     1 status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
     2                                             const sp<IBinder>& remoteCallback) {
     3     status_t status = client->initialize(mModule); //这个mModule很关键,是在CameraService.cpp中onFirstRef中获取的。其实就是根据类名等规则加载一个动态库,一般在/system/lib/hw/目录下,如camera.msm8994.so

    4 if (status != OK) {
     5         ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
     6         return status;
     7     }
     8     if (remoteCallback != NULL) {
     9         remoteCallback->linkToDeath(this);
    10     }
    11 
    12     return OK;
    13 }

            上面client中的initialize会调用到hardware interface中的initialize并设置callback (CameraHardwareInterface.h),而在这里就会调用到具体厂家HAL层的函数了。

     1     status_t initialize(hw_module_t *module)
     2     {
     3         ALOGI("Opening camera %s", mName.string());
     4         camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
     5         camera_info info;
     6         status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
     7         if (res != OK) return res;
     8         ALOGI("init hal-ver:%d,dev-ver %d",module->module_api_version,info.device_version);// 515=v2.3,770=v3.2
     9         int rc = OK;
    10         if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
    11             info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {ALOGI("open legacy");
    12             // Open higher version camera device as HAL1.0 device.
    13             rc = cameraModule->open_legacy(module, mName.string(),  // 这个cameraModule就上具体厂家代码编译出来的so库,这里对应QCamera2Factory.cpp
    14                                                CAMERA_DEVICE_API_VERSION_1_0,
    15                                                (hw_device_t **)&mDevice);
    16         } else {
    17             rc = CameraService::filterOpenErrorCode(module->methods->open(
    18                 module, mName.string(), (hw_device_t **)&mDevice));
    19         }
    20         if (rc != OK) {
    21             ALOGE("Could not open camera %s: %d", mName.string(), rc);
    22             return rc;
    23         }
    24         initHalPreviewWindow();
    25         return rc;
    26     }

    5.到这里就正式进入HAL层,每个厂家的实现代码也变得不一样,但大致模式还是差不多,都是通过V4L2的命令接口来控制具体的Camera设备。 HAL及driver将在另一篇继续讨论。

  • 相关阅读:
    ADO.NET 中的数据并发
    net中前台javascript与后台c#函数相互调用
    js正则函数match、exec、test、search、replace、split使用介绍集合
    jQuery遍历Table tr td td中包含标签
    SQL你必须知道的-查询聚合分组排序
    haut-1280 诡异的迷宫
    int、long long等的取值范围
    codeforce 855B
    nyoj-2357
    codeforces 858A
  • 原文地址:https://www.cnblogs.com/potato-coffee/p/5318543.html
Copyright © 2020-2023  润新知