OpenHarmony-v3.0-LTS Camera相机驱动框架L2解析1_初始化
发布时间:2022-01-15 10:41 所属栏目:52 来源:互联网
导读:说明 解析源码基于 OpenHarmony-v3.0-LTS 版本,代码结构和部分源码与当前维护的主线分支有差别。 解析示例代码 drivers\peripheral\camera\hal\init\demo_main.cpp 1. 简介 HarmonyOS 相机驱动框架模型对上实现相机HDI接口,对下实现相机Pipeline模型,管理
说明 解析源码基于 OpenHarmony-v3.0-LTS 版本,代码结构和部分源码与当前维护的主线分支有差别。 解析示例代码 drivers\peripheral\camera\hal\init\demo_main.cpp 1. 简介 HarmonyOS 相机驱动框架模型对上实现相机HDI接口,对下实现相机Pipeline模型,管理相机各个硬件设备。 各层的基本概念如下: HDI实现层,对上实现OHOS相机标准南向接口。 框架层,对接HDI实现层的控制、流的转发,实现数据通路的搭建、管理相机各个硬件设备等功能。 适配层,屏蔽底层芯片和OS差异,支持多平台适配。 2. 框架图 OpenHarmony-v3.0-LTS Camera相机驱动框架(L2)解析1_初始化-鸿蒙HarmonyOS技术社区 3. 代码结构 drivers\peripheral\camera ├── hal │ ├── adapter //芯片和平台适配层 │ ├── buffer_manager //buffer管理 │ ├── device_manager //设备控制接口定义 │ ├── hdi_impl //HDI Implementation实现 │ │ ├── include │ │ ├── src │ │ │ ├── camera_device //Device │ │ │ ├── camera_host //Host │ │ │ ├── offline_stream_operator //OffineStreamOperator │ │ │ └── stream_operator //StreamOperator │ │ └── test │ ├── include │ ├── init //HiSpark 3516 demo 代码 │ ├── pipeline_core │ │ ├── host_stream │ │ │ ├── include │ │ │ └── src │ │ ├── include │ │ ├── ipp //ipp │ │ │ ├── include │ │ │ └── src │ │ ├── nodes //基础通用node │ │ │ ├── include │ │ │ └── src │ │ │ ├── dummy_node │ │ │ ├── fork_node │ │ │ ├── merge_node │ │ │ ├── node_base │ │ │ ├── sensor_node │ │ │ ├── sink_node │ │ │ ├── source_node │ │ │ └── transform_node │ │ ├── pipeline_impl //pipeline构建实现 │ │ │ ├── include │ │ │ └── src │ │ │ ├── builder │ │ │ ├── dispatcher │ │ │ ├── parser │ │ │ └── strategy │ │ │ └── config │ │ ├── src //PipelineCore │ │ └── utils ├── hal_c //hal层 C实现接口 │ ├── hdi_cif │ │ ├── include │ │ └── src │ └── include └── interfaces //Camera Host框架HDI接口 └── include ├── callback //框架涉及的所有callback接口 │ ├── device │ ├── host │ └── operator ├── client └── server 4. 源码解析 上层demo代码相对简单,这里只贴出关键部分代码 int main(int argc, char** argv) { RetCode rc = RC_OK; auto mainDemo = std::make_shared<Hos3516Demo>(); rc = mainDemo->InitSensors(); if (rc == RC_ERROR) { CAMERA_LOGE("main test: mainDemo->InitSensors() error\n"); return -1; } rc = mainDemo->InitCameraDevice(); if (rc == RC_ERROR) { CAMERA_LOGE("main test: mainDemo->InitCameraDevice() error\n"); return -1; } ...... return RC_OK; } 4.1 Hos3516Demo::InitSensors() 4.1.1 上层代码 上层获取HDI层的ICameraHost:设备管理接口,并设置Host层的回调。 constexpr const char *DEMO_SERVICE_NAME = "camera_service"; RetCode Hos3516Demo::InitSensors() { int rc = 0; CAMERA_LOGD("demo test: InitSensors enter"); if (demoCameraHost_ != nullptr) { return RC_OK; } demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME); if (demoCameraHost_ == nullptr) { CAMERA_LOGE("demo test: ICameraHost::Get error"); return RC_ERROR; } hostCallback_ = new CameraHostCallback(); rc = demoCameraHost_->SetCallback(hostCallback_); if (rc != Camera::NO_ERROR) { CAMERA_LOGE("demo test: demoCameraHost_->SetCallback(hostCallback_) error"); return RC_ERROR; } CAMERA_LOGD("demo test: InitSensors exit"); return RC_OK; } 4.1.2 时序图 OpenHarmony-v3.0-LTS Camera相机驱动框架(L2)解析1_初始化-鸿蒙HarmonyOS技术社区 CameraHostProxy 提供上层调用的代理接口。 CameraHostStub 提供对应代理接口的HDI层的 ‘桩’。 CameraHostImpl 是接口层的具体实现。 Proxy-Stub 负责上下接口参数的数据转换等工作。 4.1.3 ICameraHost::Get(const char *serviceName) 从ServiceManager中取出CameraHostProxy。并返回ICameraHost接口类指针 //drivers\peripheral\camera\interfaces\include\client\camera_host_proxy.cpp sptr<ICameraHost> ICameraHost::Get(const char *serviceName) { do { using namespace OHOS::HDI::ServiceManager::V1_0; auto servMgr = IServiceManager::Get(); if (servMgr == nullptr) { HDF_LOGE("%s: IServiceManager failed!", __func__); break; } auto remote = servMgr->GetService(serviceName); if (remote != nullptr) { sptr<CameraHostProxy> hostSptr = iface_cast<CameraHostProxy>(remote); return hostSptr; } HDF_LOGE("%s: GetService failed! serviceName = %s", __func__, serviceName); } while(false); HDF_LOGE("%s: get %s failed!", __func__, serviceName); return nullptr; } 4.1.4 CameraHostProxy::SetCallback(const OHOS::sptr &callback) ICameraHostCallback 回调接口类定义了下面两个回调接口,在CameraHostCallback类中具体实现并通过IPC通讯最终设置到CameraHostImpl virtual void OnCameraStatus(const std::string &cameraId, CameraStatus status) = 0; virtual void OnFlashlightStatus(const std::string &cameraId, FlashlightStatus status) = 0; client::host_proxy发起IPC —> server::host_service_stub 注意 这里有个坑! 通常 SendRequest() 和 OnRemoteRequest() 是一对。sendRequest()在client::XXX_proxy调用,OnRemoteRequest() 在server::XXX_stub调用。但是CamereaHost 的OnRemoteRequest是由 HDF中的 HdfCameraService来接收 通过Dispatch接口再调用具体的CameraHostStub!! 这里的proxy和stub 的cmdID 宏定义名字不一样,不太利于代码阅读。 //drivers\peripheral\camera\interfaces\include\client\camera_host_proxy.cpp CamRetCode CameraHostProxy::SetCallback(const OHOS::sptr<ICameraHostCallback> &callback) { ...... int32_t ret = Remote()->SendRequest(CMD_CAMERA_HOST_REMOTE_SET_CALLBACK, data, reply, option); ...... return static_cast<CamRetCode>(reply.ReadInt32()); } //drivers\peripheral\camera\interfaces\include\server\camera_host_service_stub.cpp int32_t CameraHostStub::CameraHostStubSetCallback( MessageParcel &data, MessageParcel &reply, MessageOption &option) { bool flag = data.ReadBool(); sptr<ICameraHostCallback> hostCallback = nullptr; if (flag) { sptr<IRemoteObject> remoteObj = data.ReadRemoteObject(); hostCallback = OHOS::iface_cast<ICameraHostCallback>(remoteObj); } CamRetCode ret = cameraHost_->SetCallback(hostCallback); if (!reply.WriteInt32(static_cast<int32_t>(ret))) { HDF_LOGE("%s: write retcode failed", __func__); return HDF_FAILURE; } return HDF_SUCCESS; } 最终调用到HDI 接口层的camera_host 完成callback的设置。 //drivers\peripheral\camera\hal\hdi_impl\src\camera_host\camera_host_impl.cpp /** * @brief 设置Host回调函数 * * @param callback Host回调函数 * @return CamRetCode */ CamRetCode CameraHostImpl::SetCallback(const OHOS::sptr<ICameraHostCallback> &callback) { DFX_LOCAL_HITRACE_BEGIN; if (callback == nullptr) { CAMERA_LOGW("host callback is null."); return INVALID_ARGUMENT; } cameraHostCallback_ = callback; DFX_LOCAL_HITRACE_END; return NO_ERROR; } 4.2 Hos3516Demo::InitCameraDevice() 4.2.1 上层代码 获取CameraIds 、获取默认前置的摄像头设备的ability、创建CameraDeviceCallbak 并OpenCamera RetCode Hos3516Demo::InitCameraDevice() { int rc = 0; CAMERA_LOGD("demo test: InitCameraDevice enter"); if (demoCameraHost_ == nullptr) { CAMERA_LOGE("demo test: InitCameraDevice demoCameraHost_ == nullptr"); return RC_ERROR; } (void)demoCameraHost_->GetCameraIds(cameraIds_); if (cameraIds_.empty()) { return RC_ERROR; } const std::string cameraId = cameraIds_.front(); demoCameraHost_->GetCameraAbility(cameraId, ability_); sptr<CameraDeviceCallback> callback = new CameraDeviceCallback(); rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_); if (rc != Camera::NO_ERROR || demoCameraDevice_ == nullptr) { CAMERA_LOGE("demo test: InitCameraDevice OpenCamera failed"); return RC_ERROR; } CAMERA_LOGD("demo test: InitCameraDevice exit"); return RC_OK; } 4.2.2 时序图 OpenHarmony-v3.0-LTS Camera相机驱动框架(L2)解析1_初始化-鸿蒙HarmonyOS技术社区 4.2.3 GetCameraIds()和GetCameraAblilty() 先来看下两个简单的设备信息获取接口。 获取系统配置中的cameraIds和CameraAbility IPC 的过程和setcallback一样 此处 略去 IPC相关代码和时序图 直接看实现CameraHostImpl::GetCameraIds() 和 CameraHostImpl::GetCameraAbility(),调用了CameraHostConfig::GetCameraIds()和CameraHostConfig::GetCameraAbility() 、、drivers\peripheral\camera\hal\hdi_impl\src\camera_host\camera_host_impl.cpp /** * @brief 获取当前可用的Camera设备列表 * * @param ids 返回的当前可用的设备列表 */ CamRetCode CameraHostImpl::GetCameraIds(std::vector<std::string> &cameraIds) { DFX_LOCAL_HITRACE_BEGIN; CameraHostConfig *config = CameraHostConfig::GetInstance(); if (config == nullptr) { return INVALID_ARGUMENT; } RetCode rc = config->GetCameraIds(cameraIds); if (rc != RC_OK) { return INVALID_ARGUMENT; } DFX_LOCAL_HITRACE_END; return NO_ERROR; } /** * @brief 获取Camera的能力集 * * @param cameraId 要获取的Camera设备id * @param ability Camera设备的能力集 * @return CamRetCode * @see CameraAbility */ CamRetCode CameraHostImpl::GetCameraAbility(const std::string &cameraId, std::shared_ptr<CameraAbility> &ability) { DFX_LOCAL_HITRACE_BEGIN; CameraHostConfig *config = CameraHostConfig::GetInstance(); if (config == nullptr) { return INVALID_ARGUMENT; } RetCode rc = config->GetCameraAbility(cameraId, ability); if (rc != RC_OK) { return INVALID_ARGUMENT; } DFX_LOCAL_HITRACE_END; return NO_ERROR; } CameraHostConfig负责从camera_host_config.hcb文件读出设备驱动信息。 //drivers\peripheral\camera\hal\hdi_impl\src\camera_host\camera_host_config.cpp RetCode CameraHostConfig::ReadConfigFile() { std::unique_ptr<HcsDeal> hcsDeal = std::make_unique<HcsDeal>(CONFIG_PATH_NAME); if (hcsDeal == nullptr) { CAMERA_LOGE("make HcsDeal failed. [pathname = %{public}s]", CONFIG_PATH_NAME.c_str()); return RC_ERROR; } RetCode rc = hcsDeal->Init(); if (rc != RC_OK) { CAMERA_LOGE("hcs deal init failed. [pathname = %{public}s]", CONFIG_PATH_NAME.c_str()); return rc; } rc = hcsDeal->GetCameraId(cameraIdMap_); if (rc != RC_OK || cameraIdMap_.empty()) { CAMERA_LOGE("config camera id not found. [pathname = %{public}s]", CONFIG_PATH_NAME.c_str()); return rc; } rc = hcsDeal->GetMetadata(cameraAbilityMap_); if (rc != RC_OK || cameraAbilityMap_.empty()) { CAMERA_LOGE("config camera ability not found. [pathname = %{public}s]", CONFIG_PATH_NAME.c_str()); return rc; } return RC_OK; } RetCode CameraHostConfig::GetCameraIds(std::vector<std::string> &cameraIds) { auto itr = cameraAbilityMap_.begin(); for (; itr != cameraAbilityMap_.end(); itr++) { cameraIds.push_back(itr->first); } return RC_OK; } RetCode CameraHostConfig::GetCameraAbility( const std::string &cameraId, std::shared_ptr<CameraAbility> &ability) { auto itr = cameraAbilityMap_.find(cameraId); if (itr != cameraAbilityMap_.end()) { ability = itr->second; return RC_OK; } return RC_ERROR; } hcb文件是由hcs文件通过build_hcs.py工具生成的具体生成的相关代码在驱动芯片适配的BUILD.gn中 //drivers/peripheral/camera/hal/adapter/chipset/hispark_taurus/BUILD.gn action("build_camera_host_config") { script = "$hdf_framework_path/tools/hc-gen/build_hcs.py" sources = [ rebase_path( "//vendor/hisilicon/Hi3516DV300/hdf_config/uhdf/camera/hal/mpp/hispark_taurus/hdi_impl/camera_host_config.hcs") ] outputs = [ "$target_gen_dir/hdi_impl/camera_host_config.hcb" ] args = [ "-o", rebase_path(outputs[0]), sources[0], ] } ohos_prebuilt_etc("camera_host_config.hcb") { deps = [ ":build_camera_host_config" ] hcs_outputs = get_target_outputs(":build_camera_host_config") source = hcs_outputs[0] relative_install_dir = "hdfconfig" subsystem_name = "hdf" part_name = "hdf" } //vendor/hisilicon/Hi3516DV300/hdf_config/uhdf/camera/hal/mpp/hispark_taurus/hdi_impl/camera_host_config.hcs root { module="sample"; camera_host_config { match_attr = "camera_host_interface"; .... ability_01 :: ability { logicCameraId = "lcam001"; physicsCameraIds = [ "CAMERA_FIRST", "CAMERA_SECOND" ]; metadata { aeAvailableAntiBandingModes = [ "OHOS_CAMERA_AE_ANTIBANDING_MODE_OFF" ]; ...... 4.2.4 OpenCamera() 先简单说下callback。 这里会先创建一个CameraDeviceCallback设备回调 作为Camera设备的回调接口。CameraDeviceCallback的接口类定义在 //drivers\peripheral\camera\interfaces\include\icamera_device_callback.h virtual void OnError(ErrorType type, int32_t errorCode) = 0; virtual void OnResult(uint64_t timestamp, const std::shared_ptr<CameraStandard::CameraMetadata> &result) = 0; 开始OpenCamera()。还是通过一次ipc 最后到HDI的camera_host CameraHostImpl::OpenCamera 先从cameraDeviceMap_中查找cameraId对应的CameraDeviceImpl,然后通过CameraDeviceImpl设置device的callback. 再通过cameraId从CameraHostConfig查出对应的phyCameraIds,在调用CameraPowerUp接口完成上电. 最后把CameraDevice的status set true. 至此上层的相机初始化就完成了。 /** * @brief 打开Camera设备 * * @param cameraId 要打开的Camera设备id * @param callback Camera设备的回调函数 * @param camera 返回的Camera设备接口 * @return CamRetCode * @see ICameraDeviceCallback * @see ICameraDevice */ CamRetCode CameraHostImpl::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &device) { CAMERA_LOGD("OpenCamera entry"); DFX_LOCAL_HITRACE_BEGIN; //这里说明参数callback必须设置!!! if (CameraIdInvalid(cameraId) != RC_OK || callback == nullptr) { CAMERA_LOGW("open camera id is empty or callback is null."); return INVALID_ARGUMENT; } auto itr = cameraDeviceMap_.find(cameraId); if (itr == cameraDeviceMap_.end()) { CAMERA_LOGE("camera device not found."); return INSUFFICIENT_RESOURCES; } CAMERA_LOGD("OpenCamera cameraId find success."); std::shared_ptr<CameraDeviceImpl> cameraDevice = std::static_pointer_cast<CameraDeviceImpl>(itr->second); if (cameraDevice == nullptr) { CAMERA_LOGE("camera device is null."); return INSUFFICIENT_RESOURCES; } CamRetCode ret = cameraDevice->SetCallback(callback); if (ret != NO_ERROR) { CAMERA_LOGW("set camera device callback faild."); return ret; } CameraHostConfig *config = CameraHostConfig::GetInstance(); if (config == nullptr) { return INVALID_ARGUMENT; } std::vector<std::string> phyCameraIds; RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds); if (rc != RC_OK) { CAMERA_LOGE("get physic cameraId failed."); return DEVICE_ERROR; } if (CameraPowerUp(cameraId, phyCameraIds) != RC_OK) { CAMERA_LOGE("camera powerup failed."); CameraPowerDown(phyCameraIds); return DEVICE_ERROR; } auto sptrDevice = deviceBackup_.find(cameraId); if (sptrDevice == deviceBackup_.end()) { deviceBackup_[cameraId] = cameraDevice.get(); } device = deviceBackup_[cameraId]; cameraDevice->SetStatus(true); CAMERA_LOGD("open camera success."); DFX_LOCAL_HITRACE_END; return NO_ERROR; } 5 这里留下了两个问题 cameraDeviceMap_中的值什么时候设置的? CameraPowerUp() 如何完成上电的功能? (编辑:ASP站长网) |
相关内容
网友评论
推荐文章
热点阅读