说明
- 解析源码基于 OpenHarmony-v3.0-LTS 版本,代码结构和部分源码与当前维护的主线分支有差别。
- 解析示例代码 drivers\peripheral\camera\hal\init\demo_main.cpp
1. 简介
HarmonyOS 相机驱动框架模型对上实现相机HDI接口,对下实现相机Pipeline模型,管理相机各个硬件设备。
各层的基本概念如下:
HDI实现层,对上实现OHOS相机标准南向接口。
框架层,对接HDI实现层的控制、流的转发,实现数据通路的搭建、管理相机各个硬件设备等功能。
适配层,屏蔽底层芯片和OS差异,支持多平台适配。
2. 框架图
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 时序图
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
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 时序图
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() 如何完成上电的功能?
将在下一章节进行解析