设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 数据 创业者 手机
当前位置: 首页 > 服务器 > 系统 > 正文

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站长网)

    网友评论
    推荐文章
      热点阅读