android camera flow and V4L2 in linux kernel--------android 调用流程

记录自己的学习过程。。。。。。。

注:1. surfaceflinger暂时不完全懂,后续研究

         2. 平台mx53

android 中文件调用流程: hardware/camera.java -----> libs/camera.camera.cpp   ------> cameraservice.cpp ------> CameraHal.cpp

                                               hardware/camera.java -----> libs/camera.camera.cpp   ------> ICamera.cpp ------> cameraservice.cpp ------> CameraHal.cpp

android 中打开摄像头驱动的基本流程:

android camera flow and V4L2 in linux kernel--------android 调用流程_第1张图片

  1. 打开camera, 函数调用流程:
                          a) 调用framework/base/core/java/android/hardware/carema.java    中的camera.open函数

    public static Camera open() {
        int numberOfCameras = getNumberOfCameras();                           //获取camera数量
        CameraInfo cameraInfo = new CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {         //看注释,好像是判断是前置摄像头,还是后置摄像头
                return new Camera(i);
            }
        }
        return null;
    }

    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(this), cameraId);              //connect to camera service
    }
                          b) native_setup会调用到android_hardware_camera.cpp文件中的android_hardware_camera_native_setup()函数

static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId)
{
    sp camera = Camera::connect(cameraId);                            //framework/base/libs/camera/camera.cpp中的connect函数,如下

    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 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());
}

                           c)调用framework/base/libs/camera/camera.cpp中的connect函数

sp Camera::connect(int cameraId)
{
    LOGV("connect");
    sp c = new Camera();                                        //申请camera
    const sp& cs = getCameraService();                  //获取camera service,在systemserver中调用并运行
    if (cs != 0) {
        c->mCamera = cs->connect(c, cameraId);                          //绑定申请的camera到camera service,详细代码如下
    }
    if (c->mCamera != 0) {
        c->mCamera->asBinder()->linkToDeath(c);
        c->mStatus = NO_ERROR;
    } else {
        c.clear();
    }
    return c;
}


                             d)调用cameraservice.cpp中的master端的connect函数

sp CameraService::connect(
        const sp& cameraClient, int cameraId) {
    int callingPid = getCallingPid();
    LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
/*下面一段,属于容错处理,特殊情况特殊对待*/
    sp client;
    if (cameraId < 0 || cameraId >= mNumberOfCameras) {                                            //camera的ID越界,超过可以使用的camera的数量
        LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
            callingPid, cameraId);
        return NULL;
    }

    Mutex::Autolock lock(mServiceLock);
    if (mClient[cameraId] != 0) {                                                                  //申请试用的camera ID是不是重复申请了,或者上次没有释放
        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 hardware = HAL_openCameraHardware(cameraId);                     //打开camera设备,并初始化相关信息,下一步贴代码,并注释
    if (hardware == NULL) {
        LOGE("Fail to open camera hardware (id=%d)", cameraId);
        return NULL;
    }
    CameraInfo info;
    HAL_getCameraInfo(cameraId, &info);                                                          //获取camera info,包括facing, rotate
    client = new Client(this, cameraClient, hardware, cameraId, info.facing,                     //初始化获取到的cameraID的camera,设置相应的service,callback,busy flag
                        callingPid);
    mClient[cameraId] = client;
    LOG1("CameraService::connect X");
    return client;
}
                         e)Hal_openCameraHardware会调用到 hardware/mx5x/libcamera/cameraHal.cpp中的函数
 
    sp HAL_openCameraHardware(int cameraId)
    {
        char *SelectedCameraName;
        int back_camera_num = 0, front_camera_num = 0;
        sp pCaptureDevice = NULL;
        sp pPPDevice = NULL;
        sppJpegEncoder = NULL;

        if (HAL_getNumberOfCameras() ==0 ){
            CAMERA_HAL_ERR("There is no configure for Cameras");
            return NULL;
        }

        SelectedCameraName = Camera_name[sCameraInfo[cameraId].facing];                   //获取对应cameraID的设备名称

        pCaptureDevice = createCaptureDevice(SelectedCameraName);                         //创建cameraID对应的设备,还么有正式打开
        pPPDevice = createPPDevice();                                                     //postprocessing device
        pJpegEncoder = createJpegEncoder(SOFTWARE_JPEG_ENC);                              //jpeg  encode,应该是拍照用的

        CameraHal *pCameraHal = new CameraHal();                                          //new CameraHal对象,并设置其中相应的device(capture, pp. jpegencode)
        if (pCameraHal->setCaptureDevice(pCaptureDevice) < 0 ||
                pCameraHal->setPostProcessDevice(pPPDevice) < 0 ||
                pCameraHal->setJpegEncoder(pJpegEncoder) < 0)
            return NULL;

        if (pCameraHal->Init() < 0)                                                       //init函数,下一步贴代码,加注释
            return NULL;

        //now the board has only one csi camera sensor, so just do mirror for it
        if(strstr(SelectedCameraName, "ov") != NULL){
            pCameraHal->setPreviewRotate(CAMERA_PREVIEW_BACK_REF);
        }

        sp hardware(pCameraHal);
        CAMERA_HAL_LOG_INFO("created the fsl Camera hal");

        return hardware;
    }

};
                         f) init 函数,cameraHal.cpp文件中

    CAMERA_HAL_ERR_RET CameraHal::Init()
    {
        CAMERA_HAL_LOG_FUNC;
        CAMERA_HAL_ERR_RET ret = CAMERA_HAL_ERR_NONE;
        mCameraReady == true;

        if ((ret = AolLocForInterBuf())<0)                       //如函数名,申请buf
            return ret;
        if ((ret = InitCameraHalParam()) < 0)                    //init函数,会打开/dev/vedio设备,不会关闭,获取支持的Format,size,Fps,等数据,(以及是否可用。。。)
            return ret;
        if (mPPDeviceNeed == true && mPPDevice == NULL)
            return CAMERA_HAL_ERR_PP_NULL;
        if ((ret = CameraMiscInit()) < 0)                       //一些相关的mutex, overlay, pp
            return ret;

        return ret;
    }
                  至此,open流程结束,主要目的是,获取一个可以使用的camera接口cameraID,并创建相对应的camera 的client,绑定到camera的service上,打开cameraID对应的device,通常情况下是/dev/vedio0等,获取相关的parameters,ctrl状况,设置busy flag, 申请buffer, 初始化overlay 的mutex等。
2. getparameters

3. setparameters

           这两个函数调用过程极其相似,详细调用过程如下:

           a)  getparameters


                              到这里,就直接返回当前设置并存放的parameters,

                              对于现在使用的平台,会继续调用DevGetInputValid---->V4l2GetInputValid---------->VIDIOC_G_CTRL获取当前camera control的状态。

                  b) setparameters类似

                             现在的平台会相继调用:DevSetSource  ----------->V4l2SetSource ------------->VIDIOC_S_CTRL 设置当前的camera control的状态。

4. start preview

               和getparameters调用流程类似,最后调用到cameraHal.cpp函数中CameraHALStartPreview函数:

    status_t CameraHal::CameraHALStartPreview()
    {
        CAMERA_HAL_LOG_FUNC;
        status_t ret = NO_ERROR;
        int  max_fps, min_fps;
        mParameters.getPreviewSize((int *)&(mCaptureDeviceCfg.width),(int *)&(mCaptureDeviceCfg.height));
        mCaptureDeviceCfg.fmt = mPreviewCapturedFormat;
        mCaptureDeviceCfg.rotate = (SENSOR_PREVIEW_ROTATE)mPreviewRotate;
        mCaptureDeviceCfg.tv.numerator = 1;
        mCaptureDevice->GetDevName(mCameraSensorName);
        if (strstr(mCameraSensorName, "uvc") == NULL){
        //according to google's doc getPreviewFrameRate & getPreviewFpsRange should support both.
        // so here just a walkaround, if the app set the frameRate, will follow this frame rate.
        if (mParameters.getPreviewFrameRate() >= 15)
            mCaptureDeviceCfg.tv.denominator = mParameters.getPreviewFrameRate();
        else{
            mParameters.getPreviewFpsRange(&min_fps, &max_fps);
            CAMERA_HAL_LOG_INFO("###start the capture the fps is %d###", max_fps);
            mCaptureDeviceCfg.tv.denominator = max_fps/1000;
        }
        }else{
                mCaptureDeviceCfg.tv.denominator = 15;
        }
        mCaptureBufNum = PREVIEW_CAPTURE_BUFFER_NUM;
        mPPbufNum = POST_PROCESS_BUFFER_NUM;
        mTakePicFlag = false;

        if ((ret = PrepareCaptureDevices()) < 0){                                 //打开设备,设置(VIDEOC_S_CTRL),mmap prepare(VIDEOC_QBUF)
            CAMERA_HAL_ERR("PrepareCaptureDevices error ");
            return ret;
        }
        if (mPPDeviceNeed){
            if ((ret = PreparePostProssDevice()) < 0){
                CAMERA_HAL_ERR("PreparePostProssDevice error");
                return ret;
            }
        }
        if ((ret = PreparePreviwBuf()) < 0){
            CAMERA_HAL_ERR("PreparePreviwBuf error");
            return ret;
        }

        if ((ret = PreparePreviwMisc()) < 0){
            CAMERA_HAL_ERR("PreparePreviwMisc error");
            return ret;
        }

        if ((ret = CameraHALPreviewStart()) < 0){                                   //关键函数,开启相关处理线程
            CAMERA_HAL_ERR("CameraHALPreviewStart error");
            return ret;
        }
        return ret;
    }
           cameraHalPreviewStart函数,是用来来气处理线程,如下

    status_t CameraHal ::CameraHALPreviewStart()
    {
        CAMERA_HAL_LOG_FUNC;
        status_t ret = NO_ERROR;
        if (mCaptureDevice->DevStart()<0)
            return INVALID_OPERATION;

        mCaptureFrameThread = new CaptureFrameThread(this);                       //这几个线程的具体实现过程以及功能,暂时不了啊.....不懂的好多啊。。。。
        mPreviewShowFrameThread = new PreviewShowFrameThread(this);
        mEncodeFrameThread = new EncodeFrameThread(this);
        if(mPPDeviceNeed){
            mPostProcessThread = new PostProcessThread(this);
            if (mPostProcessThread == NULL)
                return UNKNOWN_ERROR;
        }

        if (mCaptureFrameThread == NULL ||
                mPreviewShowFrameThread == NULL ||
                mEncodeFrameThread == NULL){
            return UNKNOWN_ERROR;
        }

        mPreviewRunning = true;
        return ret;
    }

5. camera.release和stoppreview 类似



你可能感兴趣的:(android)