高通Camera驱动(1)--Camx架构介绍

深渊向深渊呼唤

之前主要做的是MTK平台camera驱动,高通平台这块只是简单了解架构。为了做成一个系列,简单梳理下高通camx架构

一、Android分层架构

      

 图片内容来自:https://source.android.google.cn/setup

     Android分层架构:

    APP:每一个应用程序由一个或多个活动组成,都是java写的

    Framework:用java编写一些规范化的模块封装框架。用Java Native Interface(JNI 是java调用native语言的一种特性,通过JNI可以使java可以调用C/C++的代码)

    Libraries系统库:核心库,主要包含基本的C库等。和我们相关主要是Bionic系统C库

    Android运行时库:提供Java编程语言核心库的大多数功能。每一个Android应用程序都在它自己的进程中运行,都有一个独立的Dalvik虚拟机实例。

    HAL:硬件抽象层,Android frameworks中JNI调用hardware.c中定义hw_get_module函数来获取硬件模块。然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相应功能。

    Linux核心层:Android的核心系统服务依赖于Linux内核。如安全性、内存管理、进程管理、网络协议栈、和驱动模型。

   SELinux:是Linux内核模块,也是Linux的一个安全子系统。主要作用最大限度地减少系统中服务进程可访问的的资源(最小权限原则)

     1.1、Camera分层架构

 

     图片来源:me

    高通平台《80-pc212-1_a_chi_api_specifications_for_qualcomm_spectra_2xx_camera.pdf》所示,对高通平台对Camxhal3有个初步的认识。

    1.2 高通平台camera架构

二、准备工作

       camera驱动开发需要在source insight 中需要加入的文件

       system仓下:   camera_metadata_tags.h、camera_metadata_tag.c、camera_metadata.c、camera_metadata.h

                          framework/av仓下 camerametadata.cpp、camerametadata.h

       kernel仓下: arch/arm/boot/dts

       hardware仓下:camera3.h等

       framework/av仓下:framework层camera文件

       vendor仓下:vendor/qcom/proprietary/camx

                            vendor\qcom\proprietary\chi-cdk\vendor\

                                                  驱动文件:actuator    eeprom  fd  flash    ois  sensor   

                                                  usecase:topology 

 

         //TODO,完善细节

三、名词解释

       Usecase :摄像机管道的特定配置,实现了已经定义良好的功能。例如,20万像素的ZSL快照和2k显示的预览是单一的用途的情况。Chi API被设计为在一定范围内指定任何可想象的用户定义用例底层硬件,不需要修改驱动程序。

       Session:单个会话是摄像机管道配置完成,从随时准备处理图像,直到摄像机管道被破坏,而另一个管道可能在它的位置配置。支持多个并行会话。

       Request:使摄像机管道处理数据的动作。这可以是请求处理从图像传感器中提取的一帧数据,或处理从存储器中提取的一帧数据。结果必须从驱动程序返回到相机应用程序。

       Sub-Request:将单个请求分解为多个内部请求的操作。驱动处理完的子请求的结果不会直接返回,而是合并成为单个结果对应原始请求。子请求用于启用诸如HDR,其中多次曝光变化的传感器需要产生单一的图像,或

                                多帧后处理,其中多个图像合并创建一个单一的输出图像。

       Steam:用于处理的具有相同大小和格式的缓冲区序列图像数据。可以指定多个不同类型的流作为相机的输入和输出管道。这组流是定义用例的关键组件。

       Per-session setting:影响相机处理管道的设置。这些设置不在会话开始时更改。例如,允许图像稳定处理。

       Per-request setting:影响单个请求的设置。例如,手动曝光值。

       拓扑结构 :表示单个用例的有向无环图(DAG)。划好了道格一系列处理节点和一组链接,它们描述正在处理的缓冲区通过这些节点。拓扑是通过XML文件指定的。

       Engine:可以用来处理数据的硬件。光谱ISP,骁龙CPU,Adreno,和DSP是Chi API可用引擎的例子。

       Node:camera管道中的一个逻辑功能块,它在单个引擎节点连接在一起形成拓扑结构。在Chi API的初始版本中,所有ISP外部的节点通过CPU代码调用,CPU代码调用本机API。本机API驱动OpenCL和FastCV等引擎。Chi API可以在未来扩                    展到允许缓存和重用硬件命令,而不需要重用本地api。

       Pipeline:支持数据操作的惟一上下文。每个管道都可以维护自己的状态跨多个请求,而不受其他管道的影响。管道利用拓扑来定义使用的引擎和数据处理流程。

       Statistics:算法包括3A,这是用来自动控制图像传感器和相机ISP,以达到更好的图像质量。这些领域特定的算法是作为Chi API的专用部分处理。

       Live Stream:处理从图像传感器接收数据的任何配置,并且不能修改以前请求中的任何数据。实时流处理速度不适合的处理传感器数据速率可以移动到offline stream去处理。

       Offline Stream:离线流处理过程不接收来自图像传感器的数据的任何配置。在Chi API中,离线流可以与实时流配对,而无需额外添加延迟。离线流的结果可以返回给相机应用程序。

四、Framework层

       MTK和高通用的都是Android的架构,在framework层的都是一样的代码。但是为了读者有更好的阅读体验,我还这里写一下这部分的代码(Android Q 之MTK代码分析(一)--Camera Hal3 Service_Cam_韦的博客-CSDN博客)

       CameraService服务启动是通过LoadBootScripts() 函数加载cameraserver.rc

       camera provider进程和cameraserver进程和底层的驱动交互,camera provider进程非常重要,camera HAL层几乎全部运行在camera provider进程中完成。

         首先看下camera provider所在源码中的位置:hardware/interfaces/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc

        

        根据Android Camera分层架构可以看出来,framework有四个组件。(CameraService、CameraDeviceClient、Camera3Device、CameraProviderManager

      1、CameraService(frameworks\av\services\camera\libcameraservice\CameraService.cpp)

CameraService::CameraService() {
    ALOGI("CameraService started (p, getpid());   
}

 

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");
    res = enumerateProviders();
}
status_t CameraService::enumerateProviders() {
    status_t res;

    //创建对象,要判断Provider对象为0才能创建
    mCameraProviderManager = new CameraProviderManager(); 
    res = mCameraProviderManager->initialize(this);
 
    deviceIds = mCameraProviderManager->getCameraDeviceIds();

    return OK;
}

          从camera分层架构来看,CameraService要创建CameraProviderMangaer

          cameraservice.cpp中 enumerateProviders枚举Provider开始创建CameraProviderManager对象并初始化

       2、CameraDeviceClient  (frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp)

CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
{

    ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}

status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
        const String8& monitorTags) {
    return initializeImpl(manager, monitorTags);
}
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {

    res = Camera2ClientBase::initialize(providerPtr, monitorTags);

    return OK;
}

        frameworks\av\services\camera\libcameraservice\common\Camera2ClientBase.cpp      

Camera2ClientBase<TClientBase>::Camera2ClientBase(
        mDevice(new Camera3Device(cameraId)),     
{
    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),String8(clientPackageName).string(), clientPid, clientUid);
}

       从这块CameraDeviceClient就创建Camera3Device对象

template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
        const String8& monitorTags) {
    return initializeImpl(manager, monitorTags);
}

template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
        const String8& monitorTags) {

    res = mDevice->initialize(providerPtr, monitorTags);

    return OK;
}

      3、Camera3Device(frameworks\av\services\camera\libcameraservice\device\Camera3Device.cpp)

          ICameraDeviceSession 这块让framework和HAL又联系在一起

status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {

    ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());

    sp<ICameraDeviceSession> session;
}

       4、CameraProviderManager(frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp)

            #include <android/hardware/camera/device/3.5/ICameraDevice.h>

           这样通过头文件的形式ICameraDevice.h,framework就和HAL的联系上

status_t CameraProviderManager::ProviderInfo::initialize(
        sp<provider::V2_4::ICameraProvider>& interface,
        hardware::hidl_bitfield<provider::V2_5::DeviceState> currentDeviceState) {
 
    ALOGI("Connecting to new camera provider: %s, isRemote? %d",
            mProviderName.c_str(), interface->isRemote());

    Status status;
    // Get initial list of camera devices, if any
    std::vector<std::string> devices;
    hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](

    hardware::Return<Status> st = interface->setCallback(this); //这块用ICameraProvider 接口连接上HAL
    ALOGI("Camera provider %s ready with %zu camera devices",
            mProviderName.c_str(), mDevices.size());

    mInitialized = true;
    return OK;
}

     ICameraProvider ,interface->setCallback(this)让framework连上HAL之后。  

    以上就是framework的四个组件,以及framework和HAL的联系

五、高通平台HAL3 camx

   5.1、这边附上一个架构图,简单直接了解camx架构

           

                图片内容来自:Android Camera简单整理(二)-Qcom HAL3 Camx架构学习 - 简书 (jianshu.com)

    5.2、CameraServer 到Provider的调用关系

     在CameraService中,主要接口在CameraService.cpp 和 Camera3Device.cpp中

     在CameraProvider总, 主要接口在CameraDevice.cpp 和CameraDeviceSession.cpp

    5.3、Provider 到 hal3的调用关系

        在provider中,mDevice->ops即为Camera3.h中的camera3_device_ops结构体

         hardware\libhardware\modules\camera\3_0\Camera.cpp

     

         这样就找到Camera hal层的函数指针的映射关系。

        映射到vendor\qcom\proprietary\camx\src\core\hal\camxhal3entry.cpp  的g_Camera3DeviceOps

        Camx的架构入口为Camx包中的camxhal3entry.cpp(\vendor\qcom\proprietary\camx\src\core\hal\camxhal3entry.cpp)      

/// Array containing hw_module_methods_t methods
static hw_module_methods_t g_hwModuleMethods =
{
    CamX::open
};

/// Array containing camera3_device_ops_t methods
#if defined (_LINUX)
static camera3_device_ops_t g_camera3DeviceOps =
{
    .initialize                         = CamX::initialize,
    .configure_streams                  = CamX::configure_streams,
    .construct_default_request_settings = CamX::construct_default_request_settings,
    .process_capture_request            = CamX::process_capture_request,
    .dump                               = CamX::dump,
    .flush                              = CamX::flush,
};
#else // _LINUX
static camera3_device_ops_t g_camera3DeviceOps =
{
    CamX::initialize,
    CamX::configure_streams,
    NULL,
    CamX::construct_default_request_settings,
    CamX::process_capture_request,
    NULL,
    CamX::dump,
    CamX::flush,
    NULL,
    {0},
};
#endif // _LINUX

/// Array of HwDeviceCloseOps to hold the close method
static HwDeviceCloseOps g_hwDeviceCloseOps =
{
    close
};

       5.4、Camx到Chi的映射

           在camhal3.cpp中,定义了g_jumpTableHAL3

            camxchitypes.h定义了CHIAppCallback结构体

            camxhal3module.h中定义了 chi_hal_callback_ops_t

            

          camhal3module.cpp 中的构造函数HAL3Module中        

                CHIHALOverrideEntry funcCHIHALOverrideEntry =
                    reinterpret_cast<CHIHALOverrideEntry>(
                        CamX::OsUtils::LibGetAddr(m_hChiOverrideModuleHandle, "chi_hal_override_entry"));

        chxextensioninterface.cpp中函数chi_hal_override_entry

        

      chi这块代码有点生疏了,看个博客快速回忆下。感谢xiaozi63大佬的博客

图片内容来自:深入理解Android相机体系结构之六_u012596975的博客-CSDN博客

      5.5、Chi到 Camx的调用

      

     5.6、Camx 到 kernel的调用

      //TODO

     以上将介绍高通平台的camx架构,后面会对这块补充细节。

 

参考文档:Android Camera简单整理(二)-Qcom HAL3 Camx架构学习 - 简书 (jianshu.com)

推荐文档:深入理解Android相机体系结构之六_u012596975的博客-CSDN博客

栏目