Camera 初始化(Open)二(HAL3中Open过程)

承接上文Camera在connect后会调度到Camera3Device->initialize函数 ,如下:

initialize:
    status_t res = manager->openSession(mId.string(), this,
                /*out*/ &session);
    mInterface = new HalInterface(session, queue);     
    return initializeCommonLocked();
        |=======>
        | 1. 创建线程StatusTracker指向的"C3Dev-%s-Status"
        | 2. 创建线程RequestThread指向的"C3Dev-%s-ReqQueue"
        |<==========================



openSession的会话调用到

frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp

status_t CameraProviderManager::openSession(const std::string &id,
        const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
        /*out*/
        sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {

    std::lock_guard<std::mutex> lock(mInterfaceMutex);

    auto deviceInfo = findDeviceInfoLocked(id,
            /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
    if (deviceInfo == nullptr) return NAME_NOT_FOUND;

    auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);

    Status status;
    hardware::Return<void> ret;
    ret = deviceInfo3->mInterface->open(callback, [&status, &session]
            (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
                status = s;
                if (status == Status::OK) {
                    *session = cameraSession;
                }
            });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                __FUNCTION__, id.c_str(), ret.description().c_str());
        return DEAD_OBJECT;
    }
    return mapToStatusT(status);
}


这里的deviceInfo3指向的mInterface是在开机时CameraService服务创建的时候,通过HIDL的机制获取的Camera HAL的服务。可以查阅Camera 初始化(Open)一(FrameWork -> Hal)

我们这儿直接进入到Hal去

hardware\interfaces\camera\device\3.2\default\cameraDevice.cpp

Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb)  {
    ...
   camera3_device_t *device;

   ATRACE_BEGIN("camera3->open");
   /*
    * 1. 调用到HAL3完成CAM_Dispatch和CAM_evntPoll这2个线程的创建
   */
   res = mModule->open(mCameraId.c_str(),reinterpret_cast<hw_device_t**>(&device));       
   ...
   /*
       * 1. 创建CameraDeviceSession
       * 2. 
   */
   session = createSession(
                device, info.static_camera_characteristics, callback);     
   ...
   //hidl返回
   _hidl_cb(status, session->getInterface());      
}


这里的Module指向的时CameraMoudle

hardware\interfaces\camera\common\1.0\default\cameraModule.cpp

int CameraModule::open(const char* id, struct hw_device_t** device) {
    int res;
    ATRACE_BEGIN("camera_module->open");
    res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
    ATRACE_END();
    return res;
}


需要注意的是这个地方的module是在CameraModule构造的时候赋值的

hardware\interfaces\camera\provider\2.4\default\cameraProvider.cpp

bool CameraProvider::initialize() {
    camera_module_t *rawModule;
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
            (const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        return true;
    }

    mModule = new CameraModule(rawModule);
    err = mModule->init();
    ...
    err = mModule->setCallbacks(this);+
    ...
    mNumberOfLegacyCameras = mModule->getNumberOfCameras();
    for (int i = 0; i < mNumberOfLegacyCameras; i++) {
    {
        struct camera_info info;
        mModule->getCameraInfo(i, &info);
        ...
        addDeviceNames(i);
    }


我的当前系统中含有CAMERA_HARDWARE_MODULE_ID的hw的库文件是只有一个camera.sdm660.so
其对应的源文件是:

hardware\qcom\camera\qcamera2\QCamera2Hal.cpp

// Camera dependencies
#include "QCamera2Factory.h"
#include "HAL3/QCamera3VendorTags.h"

static hw_module_t camera_common = {
    .tag                    = HARDWARE_MODULE_TAG,
    .module_api_version     = CAMERA_MODULE_API_VERSION_2_4,
    .hal_api_version        = HARDWARE_HAL_API_VERSION,
    .id                     = CAMERA_HARDWARE_MODULE_ID,
    .name                   = "QCamera Module",
    .author                 = "Qualcomm Innovation Center Inc",
    .methods                = &qcamera::QCamera2Factory::mModuleMethods,
    .dso                    = NULL,
    .reserved               = {0}
};

camera_module_t HAL_MODULE_INFO_SYM = {
    .common                 = camera_common,
    .get_number_of_cameras  = qcamera::QCamera2Factory::get_number_of_cameras,
    .get_camera_info        = qcamera::QCamera2Factory::get_camera_info,
    .set_callbacks          = qcamera::QCamera2Factory::set_callbacks,
    .get_vendor_tag_ops     = qcamera::QCamera3VendorTags::get_vendor_tag_ops,
    .open_legacy            = qcamera::QCamera2Factory::open_legacy,
    .set_torch_mode         = qcamera::QCamera2Factory::set_torch_mode,
    .init                   = NULL,
    .reserved               = {0}
};


hardware\qcom\camera\qcamera2\QCamera2Factory.cpp

int QCamera2Factory::cameraDeviceOpen(int camera_id,
                    struct hw_device_t **hw_device)
{
        ...
        QCamera3HardwareInterface *hw = new QCamera3HardwareInterface(mHalDescriptors[camera_id].cameraId,
        ...
        rc = hw->openCamera(hw_device);
}

int QCamera2Factory::camera_device_open(
    const struct hw_module_t *module, const char *id,
    struct hw_device_t **hw_device)
{
    int rc = NO_ERROR;
    if (module != &HAL_MODULE_INFO_SYM.common) {
        LOGE("Invalid module. Trying to open %p, expect %p",
            module, &HAL_MODULE_INFO_SYM.common);
        return INVALID_OPERATION;
    }
    if (!id) {
        LOGE("Invalid camera id");
        return BAD_VALUE;
    }
#ifdef QCAMERA_HAL1_SUPPORT
    if(gQCameraMuxer)
        rc =  gQCameraMuxer->camera_device_open(module, id, hw_device);
    else
#endif
        rc = gQCamera2Factory->cameraDeviceOpen(atoi(id), hw_device);
    return rc;
}

struct hw_module_methods_t QCamera2Factory::mModuleMethods = {
    .open = QCamera2Factory::camera_device_open,
};


很明显进入了QCamera3HardwareInterface->openCamera
从这里开始正式的进入了HAL3的流程

Android架构分析之硬件抽象层_转载和创作优秀的博客-CSDN博客

hardware\qcom\camera\qcamera2\stack\mm-camera-interface\src\mm_camera_interface.c

camera_open
    cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
    cam_obj->vtbl.ops = &mm_camera_ops;
    rc = mm_camera_open(cam_obj);
    |=======>mm_camera_open (mm_camera.c)
    |my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
    |snprintf(my_obj->evt_thread.threadName, THREAD_NAME_SIZE, "CAM_Dispatch");
    |mm_camera_cmd_thread_launch(&my_obj->evt_thread,
    |                            mm_camera_dispatch_app_event,
    |                            (void *)my_obj);
    |snprintf(my_obj->evt_poll_thread.threadName, THREAD_NAME_SIZE, "CAM_evntPoll");
    |mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
                                 MM_CAMERA_POLL_TYPE_EVT);
    | //下面这步会将/dev/videoX加入到poll的线程中。                            
    |mm_camera_evt_sub(my_obj, TRUE);
    |<==========================
  


如上Camera在open的时候还会开启线程"CAM_Dispatch"和"CAM_evntPoll"

mm_camera_cmd_thread_launch 这个线程完成命令的分发,具体的命令如下:

typedef enum
{
    MM_CAMERA_CMD_TYPE_DATA_CB,    /* dataB CMD */
    MM_CAMERA_CMD_TYPE_EVT_CB,     /* evtCB CMD */
    MM_CAMERA_CMD_TYPE_EXIT,       /* EXIT */
    MM_CAMERA_CMD_TYPE_REQ_DATA_CB,/* request data */
    MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB,    /* superbuf dataB CMD */
    MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY, /* configure notify mode */
    MM_CAMERA_CMD_TYPE_START_ZSL, /* start zsl snapshot for channel */
    MM_CAMERA_CMD_TYPE_STOP_ZSL, /* stop zsl snapshot for channel */
    MM_CAMERA_CMD_TYPE_FLUSH_QUEUE, /* flush queue */
    MM_CAMERA_CMD_TYPE_GENERAL,  /* general cmd */
    MM_CAMERA_CMD_TYPE_MAX
} mm_camera_cmdcb_type_t;


callback函数mm_camera_cmd_thread->mm_camera_dispatch_app_event->my_obj->evt.evt[i].evt_cb(...)

mm_camera_poll_thread_launch线程主要完成EVT事件和DATA事件的Poll监听,例如最重要的"/dev/videoX"事件的到来

typedef enum {
    MM_CAMERA_POLL_TYPE_EVT,
    MM_CAMERA_POLL_TYPE_DATA,
    MM_CAMERA_POLL_TYPE_MAX
} mm_camera_poll_thread_type_t;


在Open的时候创建的是EVT事件。

本篇文章的最后,我们来看下mm_camera_evt_sub订阅事件的过程

mm_camera_evt_sub(my_obj, TRUE)

这里的TRUE意味着订阅事件,FALSE意味着取消订阅. 我们这儿分析事件订阅流程

int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
                          uint8_t reg_flag)
{
    int32_t rc = 0;
    struct v4l2_event_subscription sub;

    memset(&sub, 0, sizeof(sub));
    sub.type = MSM_CAMERA_V4L2_EVENT_TYPE;
    sub.id = MSM_CAMERA_MSM_NOTIFY;
    if(FALSE == reg_flag) {
        /* unsubscribe */
        ...
    } else {
        rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
        if (rc < 0) {
            LOGE("subscribe event rc = %d, errno %d",
             rc, errno);
            return rc;
        }
        /* add evt fd to polling thread when subscribe the first event */
        rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread,
                0, my_obj->my_hdl, my_obj->ctrl_fd, mm_camera_event_notify,
               (void*)my_obj, mm_camera_sync_call);
        |=======>
        |poll_cb->poll_entries[idx].fd = fd; //这里的fd:my_obj->ctrl_fd也就是"/dev/videoX"
        |poll_cb->poll_entries[idx].handler = handler;
        |poll_cb->poll_entries[idx].notify_cb = notify_cb;//指的是mm_camera_event_notify
        |poll_cb->poll_entries[idx].user_data = userdata;
        |rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
        |<==========================
              |=======>
              | //下面这步唤醒PIPE管道
              |ssize_t len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt));
              | //下面这步唤醒PIPE管道
    }
    return rc;
}
mm_camera_poll_thread_launch(线程被唤醒)
    ->mm_camera_poll_thread
        ->mm_camera_poll_fn
            ->mm_camera_poll_proc_pipe


如下在poll的事件中加入了"/dev/videoX"后,再次调用poll完成监听

stati` void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb)
{
    ...
    switch (cmd_evt.cmd) {
    case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED:
    case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED_ASYNC:
        /* we always have index 0 for pipe read */
        poll_cb->num_fds = 0;
        poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->pfds[0];
        poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
        poll_cb->num_fds++;    
        ...
        }
}



我们之前提到还有一个线程 CAM_dataPoll,这个线程就是CameraPreview数据接收线程,看看是何时被创建的

hardware\interfaces\camera\device\3.2\default\CameraDevice.cpp

sp<CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
        const camera_metadata_t* deviceInfo,
        const sp<ICameraDeviceCallback>& callback) {
    return new CameraDeviceSession(device, deviceInfo, callback);
}
CameraDeviceSession::CameraDeviceSession
    CameraDeviceSession::initialize()
        mDevice->ops->initialize(mDevice, this)
            QCamera3HardwareInterface::initialize
                mCameraHandle->ops->add_channel



hardware\qcom\camera\qcamera2\hal3\QCamera3HWI.cpp

int QCamera3HardwareInterface::initialize(
        const struct camera3_callback_ops *callback_ops)
{
    ...
    //注意这条信道没有回调函数
    mChannelHandle = mCameraHandle->ops->add_channel(
            mCameraHandle->camera_handle, NULL, NULL, this);
   ...
}


hardware\qcom\camera\qcamera2\stack\mm-camera-interface\src\mm_camera.c

uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj,
                               mm_camera_channel_attr_t *attr,
                               mm_camera_buf_notify_t channel_cb,
                               void *userdata)
{
    mm_channel_t *ch_obj = NULL;
    uint8_t ch_idx = 0;
    uint32_t ch_hdl = 0;
    
    //取出 HAL3 中 mm_camera_obj_t 指向的 Channel[],这是个数组,最多可以保存6个信道
    for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) {
        if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) {
            ch_obj = &my_obj->ch[ch_idx];
            break;
        }
    }
    //初始化这个信道
    if (NULL != ch_obj) {
        /* initialize channel obj */
        memset(ch_obj, 0, sizeof(mm_channel_t));
        ch_hdl = mm_camera_util_generate_handler_by_num(my_obj->my_num, ch_idx);
        ch_obj->my_hdl = ch_hdl;
        ch_obj->state = MM_CHANNEL_STATE_STOPPED;
        ch_obj->cam_obj = my_obj;
        pthread_mutex_init(&ch_obj->ch_lock, NULL);
        ch_obj->sessionid = my_obj->sessionid;
        mm_channel_init(ch_obj, attr, channel_cb, userdata);
    }

    pthread_mutex_unlock(&my_obj->cam_lock);
    return ch_hdl;
}    


hardware\qcom\camera\qcamera2\stack\mm-camera-interface\src\mm_camera_channel.c

int32_t mm_channel_init(mm_channel_t *my_obj,
                        mm_camera_channel_attr_t *attr,
                        mm_camera_buf_notify_t channel_cb,
                        void *userdata)
{
    int32_t rc = 0;

    my_obj->bundle.super_buf_notify_cb = channel_cb;
    my_obj->bundle.user_data = userdata;
    if (NULL != attr) {
        my_obj->bundle.superbuf_queue.attr = *attr;
    }

    my_obj->num_s_cnt = 0;
    memset(&my_obj->frame_sync, 0, sizeof(my_obj->frame_sync));
    pthread_mutex_init(&my_obj->frame_sync.sync_lock, NULL);
    mm_muxer_frame_sync_queue_init(&my_obj->frame_sync.superbuf_queue);
    my_obj->bundle.is_cb_active = 1;
    LOGD("my_obj->bundle.is_cb_active = %d", my_obj->bundle.is_cb_active);

    LOGD("Launch data poll thread in channel open");
    snprintf(my_obj->poll_thread[0].threadName, THREAD_NAME_SIZE, "CAM_dataPoll");
    mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
                                 MM_CAMERA_POLL_TYPE_DATA);

    /* change state to stopped state */
    my_obj->state = MM_CHANNEL_STATE_STOPPED;
    return rc;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值