高通camera架构

工作记录 从JNI往下看


JNI : frameworks/base/core/jni/android_hardware_camera.cpp

static JNINativeMethod camMethods[] = {
  { "getNumberOfCameras",    "()I",    (void *)android_hardware_Camera_getNumberOfCameras },
  { "getCameraInfo",    "(ILandroid/hardware/Camera$CameraInfo;)V",   

                                                                                                  (void*)android_hardware_Camera_getCameraInfo },
  { "native_setup",    "(Ljava/lang/Object;II)V",    (void*)android_hardware_Camera_native_setup },
  { "native_release",    "()V",    (void*)android_hardware_Camera_release },
  { "setPreviewDisplay",    "(Landroid/view/Surface;)V",    (void *)android_hardware_Camera_setPreviewDisplay },
  { "startPreview",    "()V",    (void *)android_hardware_Camera_startPreview },
  { "stopPreview",    "()V",    (void *)android_hardware_Camera_stopPreview },
  { "previewEnabled",    "()Z",    (void *)android_hardware_Camera_previewEnabled },
  { "setHasPreviewCallback",    "(ZZ)V",    (void *)android_hardware_Camera_setHasPreviewCallback },
  { "addCallbackBuffer",    "([B)V",    (void *)android_hardware_Camera_addCallbackBuffer },
  { "native_autoFocus",   "()V",    (void *)android_hardware_Camera_autoFocus },
  { "native_encodeData",    "()V",    (void *)android_hardware_Camera_encodeData },
  { "native_cancelAutoFocus",    "()V",    (void *)android_hardware_Camera_cancelAutoFocus },
  { "native_takePicture",   "()V",    (void *)android_hardware_Camera_takePicture },
  { "native_setHistogramMode",    "(Z)V",    (void *)android_hardware_Camera_setHistogramMode },
  { "native_sendHistogramData",    "()V",    (void *)android_hardware_Camera_sendHistogramData },
  { "native_setFaceDetectionCb",    "(Z)V",    (void *)android_hardware_Camera_setFaceDetectionCb },
  { "native_sendMetaData",    "()V",    (void *)android_hardware_Camera_sendMetaData },
  { "native_setParameters",    "(Ljava/lang/String;)V",    (void *)android_hardware_Camera_setParameters },
  { "native_getParameters",    "()Ljava/lang/String;",    (void *)android_hardware_Camera_getParameters },
  { "reconnect",    "()V",    (void*)android_hardware_Camera_reconnect },
  { "lock",    "()V",    (void*)android_hardware_Camera_lock },
  { "unlock",    "()V",    (void*)android_hardware_Camera_unlock },
  { "startSmoothZoom",    "(I)V",    (void *)android_hardware_Camera_startSmoothZoom },
  { "stopSmoothZoom",    "()V",    (void *)android_hardware_Camera_stopSmoothZoom },
  { "setDisplayOrientation",  "(I)V",  (void *)android_hardware_Camera_setDisplayOrientation },
};

====================================================================================

static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz)
{
    return Camera::getNumberOfCameras();
}

此处调到/framework/base/libs/camera/camera.cpp 中。

int32_t Camera::getNumberOfCameras()
{
    const sp<ICameraService>& cs = getCameraService();
    if (cs == 0) return 0;
    return cs->getNumberOfCameras();
}

此处调用到/framework/base/service/camera/libcameraservice/cameraservice.cpp中借口

int32_t CameraService::getNumberOfCameras() {
    return mNumberOfCameras;
}

而,此处mNumberOfCamerascameraservice.cpp

 mNumberOfCameras =HAL_getNumberOfCameras(); 获得。


HAL_getNumberOfCameras()函数,调用\vendor\qcom\android-open\libcamera2\QualcommCameraHardware.cpp中的接口。

extern "C" int HAL_getNumberOfCameras()
{
    QualcommCameraHardware::getCameraInfo();
    return HAL_numOfCameras;
}

接下来看下getCameraInfo()


void QualcommCameraHardware::getCameraInfo()
{
    LOGI("getCameraInfo: IN");
    mm_camera_status_t status;

#if DLOPEN_LIBMMCAMERA
    void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
    LOGI("getCameraInfo: loading libqcamera at %p", libhandle);
    if (!libhandle) {
        LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
    }
    *(void **)&LINK_mm_camera_get_camera_info =
        ::dlsym(libhandle, "mm_camera_get_camera_info");
#endif
    storeTargetType();
    status = LINK_mm_camera_get_camera_info(HAL_cameraInfo, &HAL_numOfCameras);
    LOGI("getCameraInfo: numOfCameras = %d", HAL_numOfCameras);
    for(int i = 0; i < HAL_numOfCameras; i++) {
        if((HAL_cameraInfo[i].position == BACK_CAMERA )&&
            mCurrentTarget == TARGET_MSM8660){
            HAL_cameraInfo[i].modes_supported |= CAMERA_ZSL_MODE;
        } else{
            HAL_cameraInfo[i].modes_supported |= CAMERA_NONZSL_MODE;
        }
        LOGI("Camera sensor %d info:", i);
        LOGI("camera_id: %d", HAL_cameraInfo[i].camera_id);
        LOGI("modes_supported: %x", HAL_cameraInfo[i].modes_supported);
        LOGI("position: %d", HAL_cameraInfo[i].position);
        LOGI("sensor_mount_angle: %d", HAL_cameraInfo[i].sensor_mount_angle);
    }

#if DLOPEN_LIBMMCAMERA
    if (libhandle) {
        ::dlclose(libhandle);
        LOGV("getCameraInfo: dlclose(libqcamera)");
    }
#endif
    LOGI("getCameraInfo: OUT");
}


在前面有#define LINK_mm_camera_get_camera_info mm_camera_get_camera_info  ,所以我们接下来到

mm_camera_get_camera_info(HAL_cameraInfo, &HAL_numOfCameras);调用到哪。

在 vendor\qcom\proprietary\mm-camera\apps\appslib\mm_camera_interface.c中有定义

mm_camera_status_t mm_camera_get_camera_info(camera_info_t* p_cam_info,
  int* p_num_cameras)
{
  int i = 0;
  int controlfd = -1;
  char device[MAX_DEV_NAME_LEN];

  CDBG("%s: [S]\n", __func__);
  mm_camera_status_t status = MM_CAMERA_SUCCESS;
  struct msm_camera_info cameraInfo;

  if (NULL == p_cam_info) {
    status = MM_CAMERA_ERR_INVALID_INPUT;
    goto ERROR;
  }

  sprintf (device, MSM_CAMERA_CONTROL, 0);
  controlfd = open(device, O_RDWR);

//此处打开的是内核注册的控制节点 "/dev/msm_camera/control%d"

// 内核一共注册了四个节点,control、config、frame、pic 对应了四组操作函数。老一点的版本是三组节点。

  if (controlfd < 0) {
    CDBG_HIGH("%s: controlfd is invalid %s", __func__, strerror(errno));
    status = MM_CAMERA_ERR_GENERAL;
    goto ERROR;
  }

  if (ioctl(controlfd, MSM_CAM_IOCTL_GET_CAMERA_INFO, &cameraInfo) < 0) {  //此处获得内核注册camera信息
    CDBG_HIGH("%s: error (%s)", __func__, strerror(errno));
    status = MM_CAMERA_ERR_GENERAL;
    goto ERROR;
  }

  CDBG("%s: num %d\n", __func__, cameraInfo.num_cameras);
  for (i=0; i < cameraInfo.num_cameras; i++) {
    p_cam_info[i].camera_id = i; 
    p_cam_info[i].modes_supported =
      (!cameraInfo.has_3d_support[i]) ? CAMERA_MODE_2D :  //前置摄像头只支持2D
      CAMERA_MODE_2D | CAMERA_MODE_3D; 
    p_cam_info[i].position =                           //在内核前置摄像头is_internal_cam[i]定义为1,后置摄像头默认为0.
      (cameraInfo.is_internal_cam[i]) ? FRONT_CAMERA : BACK_CAMERA;

//到此用户层将前置和后置摄像头区分开
    p_cam_info[i].sensor_mount_angle = cameraInfo.s_mount_angle[i];
  }
  *p_num_cameras = cameraInfo.num_cameras;
  ERROR:
  if (controlfd > 0) {
    close(controlfd);
  }
  CDBG("%s: %d [E]", __func__, status);
  return status;
}


至此 android_hardware_Camera_getNumberOfCameras 的流程完成。

====================================================================================


2、android_hardware_Camera_getCameraInfo(JNI)

static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
    jint cameraId, jobject info_obj)
{
    CameraInfo cameraInfo;
    status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);

    if (rc != NO_ERROR) {
        jniThrowException(env, "java/lang/RuntimeException",
                          "Fail to get camera info");
        return;
    }
    env->SetIntField(info_obj, fields.facing, cameraInfo.facing);
    env->SetIntField(info_obj, fields.mode, cameraInfo.mode);
    env->SetIntField(info_obj, fields.orientation, cameraInfo.orientation);
}

此处getCameraInfo调到/framework/base/libs/camera/camera.cpp 中接口。

status_t Camera::getCameraInfo(int cameraId,
                               struct CameraInfo* cameraInfo) {
    const sp<ICameraService>& cs = getCameraService();
    if (cs == 0) return UNKNOWN_ERROR;
    return cs->getCameraInfo(cameraId, cameraInfo);
}

此处调用到/framework/base/service/camera/libcameraservice/cameraservice.cpp中接口。

status_t CameraService::getCameraInfo(int cameraId,
                                      struct CameraInfo* cameraInfo) {
    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
        return BAD_VALUE;
    }

    HAL_getCameraInfo(cameraId, cameraInfo);
    return OK;
}

HAL_getCameraInfo函数,调用\vendor\qcom\android-open\libcamera2\QualcommCameraHardware.cpp中的接口。

 

extern "C" voidHAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
{
    int i;
    char mDeviceName[PROPERTY_VALUE_MAX];
    if(cameraInfo == NULL) {
        LOGE("cameraInfo is NULL");
        return;
    }

    property_get("ro.product.device",mDeviceName," ");//获取系统属性

    for(i = 0; i < HAL_numOfCameras; i++) {
        if(i == cameraId) {
            LOGI("Found a matching camera info for ID %d", cameraId);
            cameraInfo->facing = (HAL_cameraInfo[i].position == BACK_CAMERA)?
                                   CAMERA_FACING_BACK : CAMERA_FACING_FRONT;
            // App Orientation not needed for 7x27 , sensor mount angle 0 is
            // enough.
            if(cameraInfo->facing == CAMERA_FACING_FRONT)
                cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle;
            else if( !strncmp(mDeviceName, "msm7625a", 8))
                cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle;
            else if( !strncmp(mDeviceName, "msm7627a", 8))
                cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle;
            else if( !strncmp(mDeviceName, "msm7627", 7))
                cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle;
            else if( !strncmp(mDeviceName, "msm8660", 7))
                cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle;
            else
                cameraInfo->orientation = ((APP_ORIENTATION - HAL_cameraInfo[i].sensor_mount_angle) + 360)%360;

            LOGI("%s: orientation = %d", __FUNCTION__, cameraInfo->orientation);
            cameraInfo->mode = 0;
            if(HAL_cameraInfo[i].modes_supported & CAMERA_MODE_2D)
                cameraInfo->mode |= CAMERA_SUPPORT_MODE_2D;
            if(HAL_cameraInfo[i].modes_supported & CAMERA_MODE_3D)
                cameraInfo->mode |= CAMERA_SUPPORT_MODE_3D;
            if((HAL_cameraInfo[i].position == BACK_CAMERA )&&
                !strncmp(mDeviceName, "msm8660", 7)){
                cameraInfo->mode |= CAMERA_ZSL_MODE;
            } else{
                cameraInfo->mode |= CAMERA_NONZSL_MODE;
            }

            LOGI("%s: modes supported = %d", __FUNCTION__, cameraInfo->mode);

            return;
        }
    }
    LOGE("Unable to find matching camera info for ID %d", cameraId);
}

}; // namespace android

在这里,应为前面在获取camera number时已经获得了HAL_cameraInfo相关信息,所以这里只是做了一些相关的配置。

===============================================================================================================

三 android_hardware_Camera_native_setup(JNI)

static voidandroid_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jint mode)
{
    sp<Camera> camera = Camera::connect(cameraId, mode);

    if (camera == NULL) {
        jniThrowException(env, "java/lang/RuntimeException",
                          "Fail to connect to camera service");
        return;
    }

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

    jclass clazz = env->GetObjectClass(thiz);
    if (clazz == NULL) {
        jniThrowException(env, "java/lang/RuntimeException", "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());
}

接下来我们看看connect 和 getstatus做了些什么。代码路径同上 

sp<Camera> Camera::connect(int cameraId, int mode)
{
    LOGV("connect");
    sp<Camera> c = new Camera();
    const sp<ICameraService>& cs = getCameraService();
    if (cs != 0) {
        c->mCamera = cs->connect(c, cameraId, mode);
    }
    if (c->mCamera != 0) {
        c->mCamera->asBinder()->linkToDeath(c);
        c->mStatus = NO_ERROR;
    } else {
        c.clear();
    }
    return c;
}

sp<ICamera> CameraService::connect(
        const sp<ICameraClient>& cameraClient, int cameraId, int mode) {
    int callingPid = getCallingPid();
    LOG1("CameraService::connect E (pid %d, id %d mode %d)", callingPid, cameraId, mode);

    sp<Client> client;
    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
        LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
            callingPid, cameraId);
        return NULL;
    }

    Mutex::Autolock lock(mServiceLock);
    if (mClient[cameraId] != 0) {
        client = mClient[cameraId].promote();
        if (client != 0) {
            if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
                LOG1("CameraService::connect X (pid %d) (the same client)",
                    callingPid);
                return client;
            } else {
                LOGW("CameraService::connect X (pid %d) rejected (existing client).",
                    callingPid);
                return NULL;
            }
        }
        mClient[cameraId].clear();
    }

    if (mBusy[cameraId]) {
        LOGW("CameraService::connect X (pid %d) rejected"
             " (camera %d is still busy).", callingPid, cameraId);
        return NULL;
    }

    sp<CameraHardwareInterface> hardware = HAL_openCameraHardware(cameraId, mode);
    if (hardware == NULL) {
        LOGE("Fail to open camera hardware (id=%d)", cameraId);
        return NULL;
    }
    CameraInfo info;
    HAL_getCameraInfo(cameraId, &info);
    client = new Client(this, cameraClient, hardware, cameraId, info.facing,
                        callingPid);
    mClient[cameraId] = client;
    LOG1("CameraService::connect X");
    return client;
}

\vendor\qcom\android-open\libcamera2\QualcommCameraHardware.cpp

extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId, int mode)
{
    int i;
    LOGI("openCameraHardware: call createInstance");
    for(i = 0; i < HAL_numOfCameras; i++) {
        if(HAL_cameraInfo[i].camera_id == cameraId) {
            LOGI("openCameraHardware:Valid camera ID %d", cameraId);
            LOGI("openCameraHardware:camera mode %d", mode);
            parameter_string_initialized = false;
            HAL_currentCameraId = cameraId;
            HAL_currentCameraMode = CAMERA_MODE_2D;
            /* The least significant two bits of mode parameter indicates the sensor mode
               of 2D or 3D. The next two bits indicates the snapshot mode of
               ZSL or NONZSL
               */
            int sensorModeMask = 0x03 & mode;
            if(sensorModeMask & HAL_cameraInfo[i].modes_supported){
                HAL_currentCameraMode = sensorModeMask;
            }else{
                LOGE("openCameraHardware:Invalid camera mode (%d) requested", mode);
                return NULL;
            }
            HAL_currentSnapshotMode = CAMERA_SNAPSHOT_NONZSL;
            //Remove values set by app other than  supported values
            mode = mode & HAL_cameraInfo[cameraId].modes_supported;
            if((mode & CAMERA_SNAPSHOT_ZSL) == CAMERA_SNAPSHOT_ZSL)
                HAL_currentSnapshotMode = CAMERA_SNAPSHOT_ZSL;
            LOGI("%s: HAL_currentSnapshotMode = %d", __FUNCTION__, HAL_currentSnapshotMode);

            return QualcommCameraHardware::createInstance(); //重点在这句
        }
    }
    LOGE("openCameraHardware:Invalid camera ID %d", cameraId);
    return NULL;
}

sp<CameraHardwareInterface> QualcommCameraHardware::createInstance() // 创建一个实例对象,如果硬件已经存在,则还回当前对象的指针,如果没有,

                                                     //则创建一个硬件对象,并还回。
{
    LOGI("createInstance: E");

    singleton_lock.lock();

    // Wait until the previous release is done.
    while (singleton_releasing) {
        if((singleton_releasing_start_time != 0) &&
                (systemTime() - singleton_releasing_start_time) > SINGLETON_RELEASING_WAIT_TIME){
            LOGV("in createinstance system time is %lld %lld %lld ",
                    systemTime(), singleton_releasing_start_time, SINGLETON_RELEASING_WAIT_TIME);
            singleton_lock.unlock();
            LOGE("Previous singleton is busy and time out exceeded. Returning null");
            return NULL;
        }
        LOGI("Wait for previous release.");
        singleton_wait.waitRelative(singleton_lock, SINGLETON_RELEASING_RECHECK_TIMEOUT);
        LOGI("out of Wait for previous release.");
    }

    if (singleton != 0) {
        sp<CameraHardwareInterface> hardware = singleton.promote();
        if (hardware != 0) {
            LOGD("createInstance: X return existing hardware=%p", &(*hardware));
            singleton_lock.unlock();
            return hardware;
        }
    }

    {
        struct stat st;
        int rc = stat("/dev/oncrpc", &st);
        if (rc < 0) {
            LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
            singleton_lock.unlock();
            return NULL;
        }
    }

    QualcommCameraHardware *cam = new QualcommCameraHardware();
    sp<QualcommCameraHardware> hardware(cam);
    singleton = hardware;

    LOGI("createInstance: created hardware=%p", &(*hardware));
    if (!cam->startCamera()) {
        LOGE("%s: startCamera failed!", __FUNCTION__);
        singleton_lock.unlock();
        return NULL;
    }

    cam->initDefaultParameters();
    singleton_lock.unlock();
    LOGI("createInstance: X");
    return hardware;
}


四 android_hardware_Camera_setPreviewDisplay(JNI)

这个接口函数的作用是为Preview分配内存。

static voidandroid_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface)
{
    LOGV("setPreviewDisplay");
    sp<Camera> camera = get_native_camera(env, thiz, NULL);
    if (camera == 0) return;

    sp<Surface> surface = NULL;
    if (jSurface != NULL) {
        surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
    }
    if (camera->setPreviewDisplay(surface) != NO_ERROR) {
        jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
    }
}

 

在camera.cpp中;

status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
{
    LOGV("setPreviewDisplay");
    sp <ICamera> c = mCamera;
    if (c == 0) return NO_INIT;
    if (surface != 0) {
        return c->setPreviewDisplay(surface->getISurface());
    } else {
        LOGD("app passed NULL surface");
        return c->setPreviewDisplay(0);
    }
}

这里跳到cameraservice.cpp 中。

status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;

    result = NO_ERROR;

    // return if no change in surface.
    // asBinder() is safe on NULL (returns NULL)
    if (surface->asBinder() == mSurface->asBinder()) {
        return result;
    }

    if (mSurface != 0) {
        LOG1("clearing old preview surface %p", mSurface.get());
        if (mUseOverlay) {
            // Force the destruction of any previous overlay
            sp<Overlay> dummy;
            mHardware->setOverlay(dummy);
            mOverlayRef = 0;
        } else {
            mSurface->unregisterBuffers();
        }
    }
    mSurface = surface;
    mOverlayRef = 0;
    // If preview has been already started, set overlay or register preview
    // buffers now.
    if (mHardware->previewEnabled() || mUseOverlay) {
        if (mUseOverlay) {
            if( mSurface != NULL)
                result = setOverlay(); //创建、初始化overlay

//在实际中对这些Surface 进行merge 可以采用两种方式,一种就是采用软件的形式来merge ,还一种就是采用硬件的方式,软件的方式就是我们的SurfaceFlinger ,而硬件的方式就是Overlay
        } else if (mSurface != 0) {
            result = registerPreviewBuffers();  //注册preview buffer
        }
    }

    return result;
}


转载于:https://my.oschina.net/u/994235/blog/342599

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值