笔记:CAMX初始化流程源码阅读(阶段输出 1)

Android

先把相机的处理逻辑定位在硬件抽象层。在Android的源码部分有v4l2_camera_hal.cpp这个模块,大致的处理逻辑是接收到应用层的拍照请求后,通过v4l2驱动获取图像再传回应用层。

其camera模块在HAL层的定义如下,需要定义一个HAL_MODULE_INFO_SYM变量用于导出:

  1. camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
  2.     .common =
  3.         {
  4.             .tag = HARDWARE_MODULE_TAG,
  5.             .module_api_version = CAMERA_MODULE_API_VERSION_2_4,
  6.             .hal_api_version = HARDWARE_HAL_API_VERSION,
  7.             .id = CAMERA_HARDWARE_MODULE_ID,
  8.             .name = "V4L2 Camera HAL v3",
  9.             .author = "The Android Open Source Project",
  10.             .methods = &v4l2_module_methods,
  11.             .dso = nullptr,
  12.             .reserved = {0},
  13.         },
  14.     .get_number_of_cameras = v4l2_camera_hal::get_number_of_cameras,
  15.     .get_camera_info = v4l2_camera_hal::get_camera_info,
  16.     .set_callbacks = v4l2_camera_hal::set_callbacks,
  17.     .get_vendor_tag_ops = v4l2_camera_hal::get_vendor_tag_ops,
  18.     .open_legacy = v4l2_camera_hal::open_legacy,
  19.     .set_torch_mode = v4l2_camera_hal::set_torch_mode,
  20.     .init = nullptr,
  21.     .reserved = {nullptr, nullptr, nullptr, nullptr, nullptr} };

通过camera_module_t可以得到一个camera3_device结构体:

  1. typedef struct camera3_device {
  2.     hw_device_t common;
  3.     camera3_device_ops_t* ops;
  4.     void* priv;
  5. } camera3_device_t;

重点关注camera3_device结构体中的camera3_device_ops_t结构体,其真正指明了camera的各个处理接口。

  1. const camera3_device_ops_t Camera::sOps = {
  2.     .initialize = default_camera_hal::initialize,
  3.     .configure_streams = default_camera_hal::configure_streams,
  4.     .register_stream_buffers = nullptr,
  5.     .construct_default_request_settings
  6.         = default_camera_hal::construct_default_request_settings,
  7.     .process_capture_request = default_camera_hal::process_capture_request,
  8.     .get_metadata_vendor_tag_ops = nullptr,
  9.     .dump = default_camera_hal::dump,
  10.     .flush = default_camera_hal::flush,
  11.     .reserved = {0},
  12. };

Android部分相机的初始化操作比较简单,只需遍历得到/dev目录下的所有video设备文件。

CAMX

CAMX的接口是兼容继承Android的,所以上述camera_module_t和camera3_device结构体都是一致的。在camxhal3entry.cpp文件下可以找到这两个结构体。

在高通chi文档的3.4节有初始化的顺序图。

CAMX open

首先看hw_module_methods_t结构体中的open函数。

open函数除了返回camera3_device结构体之外,还用到了单例类HAL3Module。目前依据文档关注到在HAL3Module的构造函数中会设置额外的回调函数以供使用,各个回调函数存在m_ChiAppCallbacks变量中。

HAL3Module构造函数中会搜索lib目录下的扩展模块动态链接库,名称格式为"com.chi.*.so",使用chi_hal_override_entry导出函数得到模块中的回调函数。

但我在源码相关搜索目录下找不到相关格式的so文件,作为问题进行保留。

CAMX configure_streams

configure_streams中有一部分工作是验证streams的有效性。根据文档里的顺序图,其中会调用之前设置的m_ChiAppCallbacks变量中的chi_initialize_override_session函数。

跟着调用顺序下来,发现调用的是ExtensionModule类的InitializeOverrideSession函数,主要的工作内容就是创建Usecase。

首先会结合camera的信息和stream的类型选择UsecaseId(GetMatchingUsecase函数),接着再结合此UsecaseId创建对应的Usecase类(CreateUsecaseObject函数)。CreateUsecaseObject是一个简单工厂方法,生成的具体Usecase会存在m_pSelectedUsecase变量中。因为高通的chi customization文档里有AdvancedCameraUsecase的创建流程,所以后续会结合这个Usecase进行学习。

AdvancedCameraUsecase

在高通chi文档的第6章有Usecase的拓扑xml介绍,<Usecase>标签基本可以算是一级标签了,因为子标签多,所以创建过程也很会复杂。后续会有pipeline和node等组件的创建,应该也是CAMX的核心,这部分目前还没看明白,之后另写文章进行记录。

总结和思考

在看了通过xml生成描述pipeline和node等数据结构的过程后,还是不清楚node是如何对应一个处理算法的,link数据结构又是怎么处理stream的流向的。

抛去open和configure_streams里面的诸多细节,会发现CAMX初始化的核心就是Usecase的创建,需要继续学习。