camera framwork的控制实现,以及数据回调

本文是在http://blog.csdn.net/wing12345678910/article/details/79088511

的基础上进一步分析学习,camera 在framwork层的如何实现操作控制流程,以及数据的回调流程


1、实际操作的控制流程:

client与server 连接成功后,server返回一个client给客户端
sp <::android::hardware::ICamera> c = mCamera;


在framworks/av/camera/camera.cpp中,通过binder机制,通过控制mCamera,就会在cameraserver执行相应操作

以startpreview为例:
status_t Camera::startPreview()
{
    sp <::android::hardware::ICamera> c = mCamera;
    if (c == 0) return NO_INIT;
    return c->startPreview(); //通过mCamera直接控制cameraserver
}




跳转到framworks/av/service/camera/libmmcameraservices/api1/CameraClient.cpp
status_t CameraClient::startPreview() {
    return startCameraMode(CAMERA_PREVIEW_MODE); //文件内调用
}



status_t CameraClient::startCameraMode(camera_mode mode) {
    switch(mode) {
        case CAMERA_PREVIEW_MODE:
            if (mSurface == 0 && mPreviewWindow == 0) {
                LOG1("mSurface is not set yet.");
            }
            return startPreviewMode(); //区分是preview模式还是recording模式
        case CAMERA_RECORDING_MODE:
            if (mSurface == 0 && mPreviewWindow == 0) {
                ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
                return INVALID_OPERATION;
            }
            return startRecordingMode();
        default:
            return UNKNOWN_ERROR;
    }
}


status_t CameraClient::startPreviewMode() {
    status_t result = NO_ERROR;

    if (mPreviewWindow != 0) {
        mHardware->setPreviewScalingMode(
            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
        mHardware->setPreviewTransform(mOrientation);
    }
    mHardware->setPreviewWindow(mPreviewWindow);
    result = mHardware->startPreview(); //mHardware为初始化的实例,用于调到interface接口
    if (result == NO_ERROR) {
        mCameraService->updateProxyDeviceState(
            ICameraServiceProxy::CAMERA_STATE_ACTIVE,
            String8::format("%d", mCameraId));
    }
    return result;
}


framworks/av/service/camera/libmmcameraservice/devices1/CameraHardwareInterface.h
    status_t startPreview()
    {
        if (mDevice->ops->start_preview)
            return mDevice->ops->start_preview(mDevice); //这里就调用到了HAL提供的相关接口
        return INVALID_OPERATION;
    }


至此就要调用到HAL相关接口,CameraHardwareInterface与HAL接口如何实现对接:

在frameorks/av/service/camera/libmmcameraservice/device1/CameraHardwareInterface.h文件的
initialize函数中:
rc = module->open(mName.string(), (hw_device_t **)&mDevice); 
其中:
1、camera_module_t *module对应定义在:hardware/qcom/camera/QCamera2/QCamera2Hal.cpp中
2、输出结果到 camera_device_t *mDevice,对应定义在:hardware/qcom/cameraQcamera2/HAL/QCamera2HAL.cpp中,此后就可以直接通过mDevice调用HAL的接口



hardware/qcom/camera/QCamera2/QCamera2Hal.cpp


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, //这里对应了调用的open接口
    .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/cameraQcamera2/HAL/QCamera2HAL.cpp


camera_device_ops_t QCamera2HardwareInterface::mCameraOps = {
    .set_preview_window =        QCamera2HardwareInterface::set_preview_window,
    .set_callbacks =             QCamera2HardwareInterface::set_CallBacks,
    .enable_msg_type =           QCamera2HardwareInterface::enable_msg_type,
    .disable_msg_type =          QCamera2HardwareInterface::disable_msg_type,
    .msg_type_enabled =          QCamera2HardwareInterface::msg_type_enabled,

    .start_preview =             QCamera2HardwareInterface::start_preview,
    .stop_preview =              QCamera2HardwareInterface::stop_preview,
    .preview_enabled =           QCamera2HardwareInterface::preview_enabled,
    .store_meta_data_in_buffers= QCamera2HardwareInterface::store_meta_data_in_buffers,

    .start_recording =           QCamera2HardwareInterface::start_recording,
    .stop_recording =            QCamera2HardwareInterface::stop_recording,
    .recording_enabled =         QCamera2HardwareInterface::recording_enabled,
    .release_recording_frame =   QCamera2HardwareInterface::release_recording_frame,

    .auto_focus =                QCamera2HardwareInterface::auto_focus,
    .cancel_auto_focus =         QCamera2HardwareInterface::cancel_auto_focus,

    .take_picture =              QCamera2HardwareInterface::take_picture,
    .cancel_picture =            QCamera2HardwareInterface::cancel_picture,

    .set_parameters =            QCamera2HardwareInterface::set_parameters,
    .get_parameters =            QCamera2HardwareInterface::get_parameters,
    .put_parameters =            QCamera2HardwareInterface::put_parameters,
    .send_command =              QCamera2HardwareInterface::send_command,

    .release =                   QCamera2HardwareInterface::release,
    .dump =                      QCamera2HardwareInterface::dump,
}; //这里的函数都对接在CmaeraHardwareInterface.h文件中






2、数据的回调流程
高通在回调数据只提供数据地址,并不会把真正的数据上传
回调函数的设置:

hardware/qcom/camera/QCamera/HAL/QCamera2HWI.cpp
void QCamera2HardwareInterface::set_CallBacks(struct camera_device *device,
        camera_notify_callback notify_cb,
        camera_data_callback data_cb,
        camera_data_timestamp_callback data_cb_timestamp,
        camera_request_memory get_memory,
        void *user)
{
    QCamera2HardwareInterface *hw =
        reinterpret_cast(device->priv);


    qcamera_sm_evt_setcb_payload_t payload; //设置回调类型,定义在hardware/qcom/camera/QCamera2/HAL/QCameraStateMachine.h
    payload.notify_cb = notify_cb;
    payload.data_cb = data_cb;
    payload.data_cb_timestamp = data_cb_timestamp;
    payload.get_memory = get_memory;
    payload.user = user;

    hw->lockAPI();
    qcamera_api_result_t apiResult;
    int32_t rc = hw->processAPI(QCAMERA_SM_EVT_SET_CALLBACKS, (void *)&payload);

    hw->unlockAPI();
}


framworks/av/service/camera/libmmcameraservice/device1/CameraHardwareInterface.h
    void setCallbacks(notify_callback notify_cb,
                      data_callback data_cb,
                      data_callback_timestamp data_cb_timestamp,
                      void* user)
    {
        mNotifyCb = notify_cb;
        mDataCb = data_cb;
        mDataCbTimestamp = data_cb_timestamp;
        mCbUser = user; //把从client传参进来的函数指针进行赋值,后续就可以直接回调到Client对应的函数


        if (mDevice->ops->set_callbacks) {
            mDevice->ops->set_callbacks(mDevice,
                                   __notify_cb,
                                   __data_cb,
                                   __data_cb_timestamp,
                                   __get_memory,
                                   this); //调用HAL层的回调函数接口
        }
    }


framworks/av/services/camera/libmmcameraservice/api1/CameraClient.cpp
该文件initialize的过程中有设置:
    mHardware->setCallbacks(notifyCallback,
            dataCallback,
            dataCallbackTimestamp,
            (void *)(uintptr_t)mCameraId); //设置CameraHardwareInterface的回调函数




并且根据不同的回调函数对应执行,这里以dataCallbackTimestamp为例:

void CameraClient::dataCallbackTimestamp(nsecs_t timestamp,
        int32_t msgType, const sp& dataPtr, void* user) {

    sp client = static_cast(getClientFromCookie(user).get());

    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr); //同文件调用
}


void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
    int32_t msgType, const sp& dataPtr) {
    sp c = mRemoteCallback;
    mLock.unlock();
    if (c != 0 && dataPtr != nullptr) {
        native_handle_t* handle = nullptr;

        if (dataPtr->size() == sizeof(VideoNativeHandleMetadata)) {
            VideoNativeHandleMetadata *metadata =
                (VideoNativeHandleMetadata*)(dataPtr->pointer());
            if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
                handle = metadata->pHandle;
            }
        }

        if (handle != nullptr) {
            {
                Mutex::Autolock l(mAvailableCallbackBuffersLock);
                mAvailableCallbackBuffers.push_back(dataPtr);
            }
            c->recordingFrameHandleCallbackTimestamp(timestamp, handle);
        } else {
            c->dataCallbackTimestamp(timestamp, msgType, dataPtr); //这里的sp c作为client端在server端的代理,通过binder调用client端的对应操作
        }
    }
}


client端执行通过binder传输过来的指令
framworks/av/camera/Camera.cpp
void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr)
{
    sp proxylistener;
    {
        Mutex::Autolock _l(mLock);
        proxylistener = mRecordingProxyListener;
    }
    if (proxylistener != NULL) {
        proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr); //这里有初始化时设置的监听相应回调
        return;
    }


    sp listener;
    {
        Mutex::Autolock _l(mLock);
        listener = mListener;
    }


    if (listener != NULL) {
        listener->postDataTimestamp(timestamp, msgType, dataPtr);
    } else {
        ALOGW("No listener was set. Drop a recording frame.");
        releaseRecordingFrame(dataPtr);
    }
}


对应不同的回调有监听执行不同方法,生明在:framworks/av/camera/Camera.h


class CameraListener: virtual public RefBase
{
public:
    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
    virtual void postData(int32_t msgType, const sp& dataPtr,
                          camera_frame_metadata_t *metadata) = 0;
    virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr) = 0;
    virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle) = 0;
};


具体的监听设置在:framworks/base/core/jni/android_hardware_camera.cpp文件的
android_hardware_Camera_native_setup函数中

    sp context = new JNICameraContext(env, weak_this, clazz, camera);
    context->incStrong((void*)android_hardware_Camera_native_setup);
    camera->setListener(context);


void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr)
{
    // TODO: plumb up to Java. For now, just drop the timestamp
    postData(msgType, dataPtr, NULL); //后续就把回调返回给了java层
}

目前梳理回调函数的流程,具体的数据流程还没有搞清楚

MediaRecorder的数据回调方法是_data_cb_timestamp

















你可能感兴趣的:(android_camera)