高通Camx Chi-cdk 经典好文

480b0916a8885d758f7c7ed2e1210c70.gif

和你一起终身学习,这里是程序员 Android

经典好文推荐,通过阅读本文,您将收获以下知识点:

一.初步认知
二.CAMX整体架构
三.CAMX CHI-CDK基本组件
四.组件之间的关系
五.基础组件与上层交互
六.日志TAG:
七.其他

网上关于高通CameraHAL3的介绍文档不多,之前做高通CameraHAL3的一些总结、整理,杂乱了一点,将就着看吧。

一.初步认知

高通CameraHAL3的架构很庞大,代码量也很巨大。

先对CAMX、Chi-CDK的关键术语、目录等有个初步认知

1.1 CAMX CHI-CDK 体系里面几个关键的概念:
  • (1).Usecase :
    顾名思义“使用案例”,也就是一个功能需求,
    比如说 ZSL 功能是一个 usecase,HDR 是一个 usecase,多摄是一个 usecase,
    一个 usecase 里面会可能包含多个 pipeline,多个功能 Feature,多个 isp 模块,多个 node。
    整个 chi-cdk 是围绕 usecase 的实现搭建的体系。

  • (2).Pipeline:
    数据流管道,比如说创建了一个 preview 流,一个 video 流管道,这些数据流是以 pipeline 管道的形式流通的

  • (3).Node:
    功能节点,我们后面分析到的 camera 算法,是以一个节点嵌套在管道流中,这个节点相当于实现了算法的内容
    比如dummyrtb 节点实现了双摄数据的融合处理,
    remosaic 节点实现了数据的重排列,
    staticaecalgo 节点实现了第三方 AEC 算法的接入等

  • (4).Target:
    目标对象,用来定义一些用到的参数信息

  • (5).Topology:
    整个 usecase,pipeline 和 note 呈现的是一个拓扑链接的结构形式,这些拓扑结构以一个 xml 的形式来描述,这个 xml 描述了整个工程 camera 功能中usecase、pipeline 流,nete 的拓扑关系及其参数的配置参数等。

SM7450 工程默认使用的是 chi-cdk/oem/qcom/topology/titan/fillmore/fillmore_usecase.xml

1.2 术语

ABF :Auto Bayer Filter,Bayer 域的降噪算法
ACE :Advanced Chroma Enhancement 高级色度增强
ADRC:automatic dynamic range compression 自动动态范围压缩
AFD :Auto Flicker Detection,频闪自动检测
ASD :Auto Scene Detection
ASF :Adaptive Spatial Filter,自适应空间滤波
BDS :Bayer Download Scaler
BPC :Bad Pixel Correction,坏点校准
BPS :Bayer processing segment(for snapshot)
CDS :Chroma DownSampler
CDK :Camera Development Kit 相机开发包
CHI :Camera Hardware Interface 相机硬件接口
CS :Chroma Suppression,色度抑制
CSID:Camera serial interface decoder module
CV :Chroma Enhancement 色度增强
DPU :Display processing unit
GTM :Global Tone Mapping, 全局色调映射
IFE :Image Front End,Sensor 输出的数据首先会到达IFE
IPE :Image processing engine
KMD :Kernal ModeDriver
LPM :low power manager(低功耗下运行)
LTM :Local Tone Mapping,局部色调映射
MCTF:Motion Compensation Temporal Filtering 录像时的多帧降噪
MCE :Memory Color Enhancement
MFNR:Multi Frame Noise Reduction 拍照时的多帧降噪
OPE :Offline Processing Engine
PDAF:phase difference auto focus,相位对焦
QCFA:Quad (Bayer Coding) Color Filter Arrangement/Array
RDI :Raw Dump Interface
RTB :Real Time Bokeh
SCE :Skin Color Enhancement, 肤色增强
TNR :temporal noise reduction,时域降噪
TFE :Thin Front End
UMD :User Mode Driver
VPU :Video processing unit(codec)
WNR :Wavelet Noise Reduction,小波降噪,Yuv域的降噪算法

1.3 主要目录
1.3.1 CAMX中有如下几个主要目录:
  • core/ :
    用于存放camx的核心实现模块,其中还包含了主要用于实现hal3接口的hal/目录,以及负责与CHI进行交互的chi/目录
  • csl/:
    用于存放主要负责camx与camera driver的通讯模块,为camx提供了统一的Camera driver控制接口
  • hwl/:
    用于存放自身具有独立运算能力的硬件node,该部分node受csl管理
  • swl/:
    用于存放自身并不具有独立运算能力,必须依靠CPU才能实现的node
1.3.2 Chi-Cdk 中有如下几个主要目录:
  • chioverride/:
    用于存放CHI实现的核心模块,负责与camx进行交互并且实现了CHI的总体框架以及具体的业务处理。
  • bin/:
    用于存放平台相关的配置项
  • topology/:
    用于存放用户自定的Usecase xml配置文件
  • node/:
    用于存放用户自定义功能的node
  • module/:
    用于存放不同sensor的配置文件,该部分在初始化sensor的时候需要用到
  • tuning/:
    用于存放不同场景下的效果参数的配置文件
  • sensor/:
    用于存放不同sensor的私有信息以及寄存器配置参数
  • actuator/:
    用于存放不同对焦模块的配置信息
  • ois/:
    用于存放防抖模块的配置信息
  • flash/:
    存放着闪光灯模块的配置信息
  • eeprom/:
    存放着eeprom外部存储模块的配置信息
  • fd/:
    存放了人脸识别模块的配置信息

二.CAMX整体架构

2.1 CAMX整体的架构图:
a626d8e1d630706f00227c2010aa40e1.jpeg
2.2 CAMX CHI-CDK通信机制

CAMX与 CHI-CDK 通过互相dlopen对方的So库,获取了对方的入口方法:

& 97cd0a4be67b05cf73e08ca694787c9a.jpeg
2.3 CameraHAL3数据流向

CamraHAL3数据流向图:

f8c7372e703a2e5c89eace6316ca63a6.jpeg

Camera数据从sensor出来,首先会经过IFE,然后分预览/视频和拍照2种情况。

如果是预览或者录像,是先经过IPE处理,最后输出到显示。

如果是拍照,则是先经过BSP处理,然后再经过JPEG编码器,最后保存为图片输出。

IFE、IPE、BPS、JPEG,它们分别表示芯片内部的硬件处理单元,

数据在这些单元内部的处理还是比较复杂的,在不同的处理单元里面,会进行一些复杂的算法处理,这里先有个认识,有个基本概念。

三.CAMX CHI-CDK基本组件

3.1 UseCase

UseCase,字面意思:用例

官方注解:

A set of streams configured by the client combined with a set of static properties specifying the processing of those streams

由客户端配置的一组流,这组流是有着一系列静态属性相结合描述的流

See createCaptureSession in the Android CameraDevice documentation

结合下面这段代码来好好理解下:

//UseCase: 预览+录像
List<Surface> surfaces = new ArrayList<>();
 
if(previewSurface != null && previewSurface.isValid()){
  surfaces.add(previewSurface);
  mPreviewBuilder.addTarget(previewSurface);
}
 
if(mMediaRecorder != null && mMediaRecorderSurface != null 
      && mMediaRecorderSurface.isValid()){
  surfaces.add(mMediaRecorderSurface);
  mPreviewBuilder.addTarget(mMediaRecorderSurface);
}
 
mCameraDevice.createCaptureSession(surfaces,...,...);

这段代码,是把预览的surface和录像的surface都设进去,然后去创建session

就是表示我预览和录像都需要拿到camera数据。

假设我预览设置的size是1080 x 720,录像是1080p的,那这个1080 x 720预览+1080p录像

就是一个usecase(用例)

其它类推。

UsecaseId:\chi-cdk\core\chiutils\chxdefs.h

/// @brief Usecase identifying enums
enum class UsecaseId
{
    NoMatch             = 0,
    Default             = 1,
    Preview             = 2,
    PreviewZSL          = 3,
    MFNR                = 4,
    MFSR                = 5,
    MultiCamera         = 6,
    QuadCFA             = 7,
    RawJPEG             = 8,
    MultiCameraVR       = 9,
    Torch               = 10,
    YUVInBlobOut        = 11,
    VideoLiveShot       = 12,
    SuperSlowMotionFRC  = 13,
    Feature2            = 14,
    Depth               = 15,
    AON                 = 16,
    MaxUsecases         = 17,
};

chi-cdk/oem/qcom/topology/titan/fillmore/fillmore_usecase.xml

d5f55d893fc5bf9cc5a9c6cc369620ed.jpeg

这个 xml 文件里面描述了 82 个 usecase,但是我们的相机不一定全部跑了这些 usecase,

这些 xml 描述的只是配置,描述的 uscase 是否实现了,还要看代码里面是否实现,并使能了这些 usecase。

比如我们常接触到的有 UsecaseTorch,UsecasePreview , UsecaseVideo, UsecaseSnapshot, UsecaseZSL, UsecaseQuadCFA,UsecaseRTB,UsecaseSAT 等

  • 选择UsecaseId

不同的UsecaseId分别对应的不同的"使用案例",

该阶段是通过调用UsecaseSelector::GetMatchingUsecase()方法来实现的,

该函数中通过传入的operation_mode、num_streams配置数据流、数量以及当前使用的Sensor个数来选择相应的UsecaseId,

比如当numPhysicalCameras值大于1,同时配置的数据流数量num_streams大于1时,选择的就是UsecaseId::MultiCamera,表示当前采用的是双摄场景。

chi-cdk\core\chiusecase\Chxusecaseutils.cpp

UsecaseId UsecaseSelector::GetMatchingUsecase(
    const LogicalCameraInfo*        pCamInfo,
    camera3_stream_configuration_t* pStreamConfig)
{
    UsecaseId usecaseId = UsecaseId::Default; //第一行代码
    ......
    CHX_LOG_INFO("usecase ID:%d",usecaseId);
    return usecaseId;                         //最后一行代码
}

chi-cdk\core\chiframework\Chxextensionmodule.h

UsecaseSelector*        m_pUsecaseSelector;                     ///< Usecase selector
UsecaseFactory*         m_pUsecaseFactory;                      ///< Usecase factory
Usecase*                m_pSelectedUsecase[MaxNumImageSensors]; ///< Selected usecase
  • 创建Usecase:

根据之前选择的UsecaseId,通过UsecaseFactory来创建相应的Usecase,

Class Usecase是所有Usecase的基类,其中定义并实现了一些通用接口,

CameraUsecaseBase继承于Usecase,并扩展了部分功能。

AdvancedCameraUsecase又继承于CameraUsecaseBase,作为主要负责大部分场景的Usecase实现类,

另外对于多摄场景,现提供了继承于AdvancedCameraUsecase的UsecaseMultiCamera来负责实现。

在这段代码中可以看到,除了双摄场景,其它大部分场景使用的都是AdvancedCameraUsecase类来创建Usecase的

chi-cdk\core\chiframework\Chxextensionmodule.cpp

CDKResult ExtensionModule::InitializeOverrideSession(
            uint32_t                        logicalCameraId,
            const camera3_device_t*         pCamera3Device,
            const chi_hal_ops_t*            chiHalOps,
            camera3_stream_configuration_t* pStreamConfig,
            int*                            pIsOverrideEnabled,
            VOID**                          pPrivate)
{
    ...
    selectedUsecaseId = m_pUsecaseSelector->GetMatchingUsecase(&m_logicalCameraInfo[logicalCameraId],
pStreamConfig);
    ...
    m_pSelectedUsecase[logicalCameraId] =
 m_pUsecaseFactory->CreateUsecaseObject(&m_logicalCameraInfo[logicalCameraId],
                                               selectedUsecaseId, m_pStreamConfig[logicalCameraId],
                                               m_multiCameraResources.hDescriptorConfig);                                                           
}

chi-cdk\core\chiusecase\Chxusecaseutils.cpp

Usecase* UsecaseFactory::CreateUsecaseObject(
LogicalCameraInfo*              pLogicalCameraInfo,     ///< camera info
UsecaseId                       usecaseId,              ///< Usecase Id
camera3_stream_configuration_t* pStreamConfig,          ///< Stream config
ChiMcxConfigHandle              hDescriptorConfig)      ///< mcx config
{
    Usecase* pUsecase  = NULL;
    UINT     camera0Id = pLogicalCameraInfo->ppDeviceInfo[0]->cameraId;
    switch (usecaseId)
    {
        case UsecaseId::PreviewZSL:
        case UsecaseId::VideoLiveShot:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
        case UsecaseId::MultiCamera:
            if ((LogicalCameraType::LogicalCameraType_Default == pLogicalCameraInfo->logicalCameraType) &&
                (pLogicalCameraInfo->numPhysicalCameras > 1))
            {
                pUsecase = ChiMulticameraBase::Create(pLogicalCameraInfo, pStreamConfig, hDescriptorConfig);
            }
            break;
        case UsecaseId::MultiCameraVR:
            //pUsecase = UsecaseMultiVRCamera::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        case UsecaseId::QuadCFA:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
        case UsecaseId::Torch:
            pUsecase = UsecaseTorch::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        case UsecaseId::Depth:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
        case UsecaseId::AON:
            pUsecase = CHXUsecaseAON::Create(pLogicalCameraInfo);
            break;
        default:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
    }
    
    return pUsecase;
}

在AdvancedCameraUsecase::Create方法中做了很多初始化操作,其中包括了以下几个阶段:

获取XML文件中Usecase配置信息
创建Feature
保存数据流,重建Usecase的配置信息
调用父类CameraUsecaseBase的initialize方法,进行一些常规初始化工作
Chi-cdk\core\chiusecase\Chxadvancedcamerausecase.cpp

  • 获取XML文件中Usecase配置信息

这一部分主要通过调用CameraUsecaseBase::GetXMLUsecaseByName方法进行实现。

该方法的主要操作是从PerNumTargetUsecases数组中找到匹配到给定的usecaseName的Usecase,并作为返回值返回给调用者,

在函数中会与默认传入的"UsecaseZSL"进行比较,更新并返回pUsecase

PerNumTargetUsecases的定义是在g_pipeline.h中,该文件是在编译过程中通过 \chi-cdk\tools\usecaseconverter\usecaseconverter.pl 脚本将定义在个平台目录下的common_usecase.xml中的内容转换生成g_pipeline.h。

/// AdvancedCameraUsecase::Create
 
AdvancedCameraUsecase* AdvancedCameraUsecase::Create(
            LogicalCameraInfo*              pCameraInfo,   ///< Camera info
            camera3_stream_configuration_t* pStreamConfig, ///< Stream configuration
            UsecaseId                       usecaseId)     ///< Identifier for usecase function
{
    AdvancedCameraUsecase* pAdvancedCameraUsecase = CHX_NEW AdvancedCameraUsecase;
    
    if ((NULL != pAdvancedCameraUsecase) && (NULL != pStreamConfig))
    {
        result = pAdvancedCameraUsecase->Initialize(pCameraInfo, pStreamConfig, usecaseId);
    }
 
    return pAdvancedCameraUsecase;
}
 
 
/// AdvancedCameraUsecase::Initialize
/// 这个函数后面会反复查看
 
static const CHAR*  ZSL_USECASE_NAME   = "UsecaseZSL";
CDKResult AdvancedCameraUsecase::Initialize(
    LogicalCameraInfo*              pCameraInfo,   ///< Camera info
    camera3_stream_configuration_t* pStreamConfig, ///< Stream configuration
    UsecaseId                       usecaseId)     ///< Identifier for the usecase function
{
    ...
    m_pAdvancedUsecase = GetXMLUsecaseByName(ZSL_USECASE_NAME);
    ...
    if (CDKResultSuccess == result)
    {
        if ((UsecaseId::PreviewZSL    == m_usecaseId) ||
            (UsecaseId::YUVInBlobOut  == m_usecaseId) ||
            (UsecaseId::VideoLiveShot == m_usecaseId) ||
            (UsecaseId::QuadCFA       == m_usecaseId) ||
            (UsecaseId::RawJPEG       == m_usecaseId) ||
            (UsecaseId::Feature2      == m_usecaseId) ||
            (UsecaseId::MultiCamera   == m_usecaseId))
            {
                SelectFeatures(pStreamConfig);
            }
        result = SelectUsecaseConfig(pCameraInfo, pStreamConfig);
    }
     ...
 }
 
 
/// CameraUsecaseBase::GetXMLUsecaseByName
 
/// @brief Collection of usecases with matching properties (target count at this point)
struct ChiTargetUsecases
{
    UINT        numUsecases;  ///< The number of Usecases in this collection
    ChiUsecase* pChiUsecases; ///< An array of Usecases of size numUsecases
};
 
ChiUsecase* CameraUsecaseBase::GetXMLUsecaseByName(const CHAR* usecaseName)
{
    ChiUsecase* pUsecase   = NULL;
    UINT32      numTargets = 0;
 
    CHX_LOG("E. usecaseName:%s", usecaseName);
 
    struct ChiTargetUsecases* pPerNumTargetUsecases = UsecaseSelector::GetValueFromUsecasepChiTargetUsecases().at(
                                                      "PerNumTargetUsecases");
 
 
    numTargets = UsecaseSelector::GetValueFromUsecaseEnum().at("PerNumTargetUsecasesSize");
  
 
    for (UINT32 i = 0; i < numTargets; i++)
    {
        if (0 < pPerNumTargetUsecases[i].numUsecases)
        {
            ChiUsecase* pUsecasePerTarget = pPerNumTargetUsecases[i].pChiUsecases;
 
            for (UINT32 index = 0; index < pPerNumTargetUsecases[i].numUsecases; index++)
            {
                if (0 == strcmp(usecaseName, pUsecasePerTarget[index].pUsecaseName))
                {
                    //传入的默认"UsecaseZSL"和挑选出来的不一致,就用挑选出来的
                    pUsecase = &pUsecasePerTarget[index];
                    break;
                }
            }
        }
    }
 
    CHX_LOG("pUsecase:%p", pUsecase);
    return pUsecase;
}

UseCase在camx中很有很多衍生类,这是camx针对不同的stream来建立不同的usecase对象,用来管理选择feature,并且创建 pipeline以及session。

e70d20563695107498751a04277da788.jpeg
3.2 Feature

Feature 代表一个特定的功能。

高通CameraHAL3的 feature 有HDR(高动态范围)、SuperNight(超级夜景)、MFNR(多帧降噪)等等。

Usecase选择相应的feature,然后关联一组pipeline,上层下发request请求,hal层会根据request去选择对应的feature。

6277eed84f26aa44fbdfd2a4681019f1.jpeg
3.3 Node

Node是单个具有独立处理功能的抽象模块,可以是软件单元也可以是硬件单元。

Node是camx中非常重要的一个父类,是处理camera 请求的一个中间节点,用于处理pipeline下发的请求。

Node结构:

cb4b95093caeacdcb8073fa93e8aa109.jpeg

创建Node流程:

fe9e45c20295850ca045afcc647b23d9.jpeg

Node 节点在camx chi架构中至关重要,数据的处理都是通过封装好的Node节点来进行的。

ef46a8a43514c7d5b2a4fa2df29d2aea.jpeg

Node初始化流程:

dc8d34ffccaf5c29619b64054a3355df.jpeg
3.4 Pipeline

一连串node的集合。pipeline提供单一特定功能的所有资源集合,维护着所有硬件资源以及数据的流转。

3.5 Session

若干个有关联的pipeline的集合,用于管理pipeline的抽象控制单元,其中至少包含一个pipeline,并控制着所有的硬件资源,管控着每个pipeline内部的request流转以及数据的输入输出。

3.6 Link

定义不同的Port的连接端口(输入端口和输出端口)

3.7 Port

作为Node的输入输出端口,使用SrcPort以及DstPort结构定义XML文件。

17a2bbd6e81f776bb3b9d516deceb9ff.jpeg
3.8 Topologies
fad69341c24a465832dbd4cb7b146d10.jpeg
有向无环图
3.9 常用Usecase、Pipeline及其对应关系

Camx、Chi-Cdk做成组件化的目的在于:

29df763a5f3d83b1855fefb07295c32e.jpeg

不同机型、产品性能及定位不同,即使基线一样usecase等也有可能不一样

给了手机厂商极大的自定义空间,UseCase可以场景复用,对应的pipeline也可以不用或复用

常用Usecase、Pipeline的对应关系:

四.组件之间的关系

4.1 基本组件之间的关系:

上层根据需求,config对应的stream下来
下面会根据申请的stream来选择对应的usecase
usecase选择完成后,又会去选择需要的feature
不同的feature会去关联对应的pipeline
pipeline是由一系列node组成的
最终上层config的stream,就会交由各个node去处理
组件关系图:

73326b32f233ef50c85ccb912accc5dd.jpeg

目前高通Camera HAL3的架构已逐步改为以Feature为中心,摒弃之前Usecase为中心的架构模式

5f0d2a5b4819bbf0eea23ecce8b094b2.jpeg

五.基础组件与上层交互

5.1 Camera App整体渲染流程以及与CAMX交互流程图:

图1

eec3e34b1d680647489158a99138a4ff.jpeg

图2:

003f87aa0bfe0d38d591402fef35b800.jpeg
5.2 Request流转

上层由Session下发的每一个Request对应了三个Result:

  • partial metadata
  • metadata
  • image data

对于每一个Result,上传过程可以大致分为以下两个阶段:

Session内部完成图像数据的处理,将结果发送至Usecase中
Usecase接收到来自Session的数据,并将其上传至Provider

5.3 Session回调函数在CAMX的体现
5.3.1 Session::StreamOn()

该方法主要用于开始硬件的数据输出

具体点儿就是进行配置Sensor寄存器,让其开始出图,并且将当前的Session的状态告知每一Node,让它们在自己内部也做好处理数据的准备,所以之后的相关Request的流转都是以该方法为前提进行的,所以该方法重要性可见一斑。

Session的StreamOn方法中主要做了如下两个工作:

    1. 调用FinalizeDeferPipeline()方法
      如果当前pipeline并未初始化,则会调用pipeline的FinalizePipeline()方法,这里方法里面会去针对每一个从属于当前pipeline的Node依次做FinalizeInitialization、CreateBufferManager、NotifyPipelineCreated以及PrepareNodeStreamOn操作

FinalizeInitialization用于完成Node的初始化动作,NotifyPipelineCreated用于通知Node当前Pipeline的状态,此时Node内部可以根据自身的需要作相应的操作,

PrepareNodeStreamOn()方法的主要是完成Sensor以及IFE等Node的控制硬件模块出图前的配置,其中包括了曝光的参数的设置

CreateBufferManagers()方法涉及到CAMX CHI-CDK中的一个非常重要的Buffer管理机制,用于Node的ImageBufferManager的创建,而该类用于管理Node中的output port的buffer申请/流转/释放等操作。

    1. 调用Pipeline的StreamOn()方法
      这个方法里面会进一步通知CSL部分开启数据流,并且调用每一个Node的OnNodeStreamOn()方法,该方法会去调用ImageBufferManager的Activate(),该方法里面会去真正分配用于装载图像数据的buffer,之后会去调用CHI部分实现的用户自定义的Nod的pOnStreamOn()方法,用户可以在该方法中做一些自定义的操作。
5.3.2 Session::ProcessCaptureRequest()

针对每一次的Request的流转,都是以该方法为入口开始的,具体流程见下图:

013c9cd22d7b6dd4b834a480962a4512.jpeg

Pipeline首次针对每一个Node通过调用AddDeferredNode方法加入到DRQ中

此时所有的Node都会加入到m_readyNodes中,然后通过调用dispatchReadyNodes方法,触发DRQ开始进行整个内部处理流程

基本流程可以参见下图:

91fac8902b25a78a0ea1898fe8ca5e68.jpeg

Session内部完成图像数据的处理后是如何将结果发送至Usecase的:

5ef6f77feb9c916eb317f4bed26cb996.jpeg

Usecase接收到Session的数据,是如何发送至Provider的,

以常用的AdvancedCameraUsecase为例进行代码的梳理:

c9f76555858ece39d181e7f5da05fe1e.jpeg

六.日志TAG:

6.1 摄像头驱动上电:

driver上电日志:cam_sensor_driver_cmd | Probe success

6.2 摄像头驱动下电:

driver下电日志:

cam_sensor_driver_cmd: CAM_STOP_DEV Success for productname_ofilm_s5khm2_wide sensor_id:0x1ad2,sensor_slave_addr:0x20

cam_sensor_driver_cmd: CAM_RELEASE_DEV Success for productname_ofilm_s5khm2_wide sensor_id:0x1ad2, slave_addr:0x20

6.3 打开摄像头开始传第一帧之前:

CAM_START_DEV

6.4 底层遍历摄像头:

CHIUSECASE: [INFO ] chifeature2graphselector.cpp:11256 BuildCameraIdSet() cameraId 4, set 54
CHIUSECASE: [INFO ] chifeature2graphselector.cpp:11256 BuildCameraIdSet() cameraId 0, set 50
CHIUSECASE: [INFO ] chifeature2graphselector.cpp:11256 BuildCameraIdSet() cameraId 1, set 50
CHIUSECASE: [INFO ] chifeature2graphselector.cpp:11256 BuildCameraIdSet() cameraId 2, set 50
CHIUSECASE: [INFO ] chifeature2graphselector.cpp:11256 BuildCameraIdSet() cameraId 3, set 50

6.5 打开相机:

CameraService: CameraService::connect|first frame arrived|CameraService: disconnect: Disconnected|CAM_ACQUIRE_DEV|CAM_START_DEV|CAM_STOP_DEV|CAM_RELEASE_DEV

"configure_streams":配置流

"pipelineName":pipeline名称

CAMX :|CHIUSECASE:|STREAM_ONSelectFeatureGraphforRequestFromTable|Node::|CamX:|CHIUSECASE:|Camera3|CameraDevice

七.其他

7.1 定义pipeline中node的xml地址:

vendor/qcom/proprietary/chi-cdk/oem/qcom/topology/titan/usecase-components/usecases/UsecaseZSL/pipelines

7.2 Node链接方式定义:

Pipeline中的Node以及连接方式都在XML中被定义,其主要包含了以下几个标签定义:

  • PipelineName: 用来定义该条Pipeline的名称
  • NodeList: 该标签中定义了该条Pipeline的所有的Node
  • PortLinkages: 该标签定义了Node上不同端口之间的连接关系
7.3 vendortag定义文件:

/vendor/qcom/proprietary/chi-cdk/api/common/chioemvendortagdefines.h

7.4 sensor驱动目录:

某项目名为productname,其一颗摄像头的驱动文件目录:

vendor\qcom\proprietary\chi-cdk\oem\qcom\sensor\productname_sensor\productname_ofilm_ov16a1q_front_sensor

原文链接:https://blog.youkuaiyun.com/geyichongchujianghu/article/details/131029549

至此,本篇已结束。转载网络的文章,小编觉得很优秀,欢迎点击阅读原文,支持原创作者,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

a06237588e67ba201c6b79ef2360727a.jpeg

点个在看,为大佬点赞!

高通CamX与OpenCamera是两个不同的概念,CamX高通公司的相机框架,而OpenCamera是一个开源的Android相机应用。因此,它们之间的代码流程是不同的。以下是OpenCamera的基本代码流程: 1. 初始化相机:OpenCamera会初始化相机设备,包括打开相机设备、配置相机参数(如分辨率、帧率、对焦模式等)。 2. 设置预览界面:OpenCamera会创建一个预览界面(SurfaceView或TextureView),用于显示相机预览画面。 3. 实现相机功能:OpenCamera实现了一系列的相机功能,如自动对焦、曝光调节、白平衡控制等。这些功能通过调用相机API来实现。 4. 拍照和录像:OpenCamera提供了拍照和录像功能。当用户点击拍照按钮时,OpenCamera会触发拍照操作,并保存照片到指定路径。而在录像模式下,OpenCamera会开始录制视频,并保存到指定路径。 5. 处理图像数据:OpenCamera在预览和拍照/录像过程中,会获取相机输出的图像数据,并进行处理。这可能包括图像增强、实时滤镜、人脸识别等操作。 6. 相机参数设置:OpenCamera还提供了一些相机参数的设置,如闪光灯模式、场景模式、ISO设置等。 7. 监听相机事件:OpenCamera会监听相机事件,如对焦完成、曝光完成等,以便在相应事件发生时作出相应的处理。 8. 释放相机资源:当不再需要使用相机时,OpenCamera会释放相机资源,包括关闭相机设备、释放预览界面等。 总的来说,OpenCamera的代码流程包括初始化相机、设置预览界面、实现相机功能、拍照和录像、处理图像数据、相机参数设置、监听相机事件和释放相机资源。这样就可以实现一个基本的相机应用程序。请注意,这只是一个简单的概述,实际的代码流程可能更加复杂和详细。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值