乐趣区

关于android:Qcom-Camx-架构二

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

本篇文章次要介绍 Android 开发中的局部知识点,通过浏览本篇文章,您将播种以下内容:

一、Android Hal3 回顾
二、Qcom Hal3 CamX 架构
三、Qcom Hal3 Camx 重点

一、Android Hal3 回顾

Camera HAL3 学习

HAL 层操作简略总结:

  1. Framework 层发送捕捉数据的异步申请。
  2. HAL 层设施必须依照秩序解决申请。对于每个申请,HAL 层须要输入元数据和一个或者多个图像数据。
  3. 对于申请和后果都须要遵循先进先出的准则;这个数据流将被后续的申请所参考。
  4. 对于同一个申请,所有输入数据的工夫戳必须雷同,以便 framework 层同步输入数据,如果需要的话。
  5. 在申请和后果数据总,所有捕捉数据的配置和状态(除了 3A 解决),都须要封装起来。

二、Qcom Hal3 CamX 架构

Qcom 作为平台厂商会依据谷歌定义的 HAL3 接口来实现本人的 Camera HAL3, 新的支流的 Qcom Camera HAL3 架构就是 CamX 了.
Camx 的具体过程可参考高通文档:
80-pc212-1_d_qualcomm_spectra_isp_camera_chi_api_reference.pdf
最次要还是要看 code, 手机厂商对该层代码有本人的改变, 可能差异还是有的, 具体我的项目大体框架统一但细节有区别, 差别和机型的高通基线也保持一致.

2.1 CamX 架构总体构造

简略总结下:

  1. Camx 的架构入口为 Camx 包中的 camxhal3entry.cpp,Camx 中是高通平台 Camx 架构的外围跳转及解决业务的代码, 个别手机厂商不会去更改, 代码目录在 vendor/qcom/proprietary/camx/ 下, 编译后果是 camera.qcom.so
  2. Camx 通过 chxentensionInterface 调用到 chi-cdk 包下的代码, 这外面个别是手机厂商本人定制性能的中央, 代码目录在 vendor/qcom/proprietary/chi-cdk/, 编译后果是 com.qti.chi.override.so
  3. 从这张图中大略晓得一个 request 来业务流程交给 camx 解决, 但会通过 chi-cdk 进行 request 定制化从新打包再交给 camx 理论去执行或和 kernel driver 层进行交互,camx 局部代码即外围流程管控的代码, 而 chi-cdk 正是手机厂商想要实现本人定制化性能的代码中央.

2.2 CamX 架构中重要的数据结构及关系

缺一张图

Usecase /Session/ Feature /pipeline/ Node

  1. Chi 对 Camx 的操作,须要通过 ExtensionModule 进行操作,因而,camx 对外提供的接口扩大须要通过 ExtensionModule 进行,外面一个重要的变量就是 g_chiContextOps。
  2. Camx 对 Chi 的操作,是通过 HAL3Module 接口的 m_ChiAppCallbacks 进行的,因而 chi 外面开释的接口,都会在 m_ChiAppCallbacks 外面体现
  3. Usecase:基本上与 App 上的各种模式有肯定的对应关系,包含 PreviewZSL,VideoLiveShot, SAT(Multicamera), RTB(Reatime Bokeh),QCFA, Dual, superslowmotionfrc…,一个 usecase 蕴含了 realtime 和 snapshot 的 session,须要蕴含所有的在这个 usecase 的所有 feature 的 pipeline 列表
  4. Feature: 在 Usecase 下关上某个功能设计的一种架构,通常状况下一个 Usecase 能够启用各种不同的 feature,feture 蕴含了 usecase 外面的局部 pipeline, 个别都是 snapshot 的才会蕴含 feature 进行解决,因而,usecase 与 feautre 的界线并不显著。
  5. Session:蕴含了 ChxSession,ChiSession 和 CamxSession。Chxsession 是对 chi 接口外面对 CamxSession 的封装,Usecase 外面创立的 Session 都是要创立这一个。ChiSession 是 camx 外面的一个局部,是对 camxSession 的继承和透传。
  6. pipeline- 蕴含单个通过验证的 topology 的可重用容器。驱动程序通过 pipeline 来理解所应用的引擎以及数据处理的流程。
  7. Node—camera pipeline 内的逻辑功能块,在单个引擎上执行。node 链接在一起形成一个 topology。在 CHI API 的初始版本中,ISP 内部的所有节点都是通过 CPU 代码调用的,调的是 native API。

不同机型, 产品性能及定位不同, 即便基线一样 usecase 等也有可能不一样, 高通这么做给了手机厂商极大的自定义空间, 举个某机型例子,UseCase 能够场景复用, 对应的 pipeline 也能够不必或复用.

2.3 CamX 操作过程

基本操作, 截图自高通文档:

具体过程:

2.3.1 Open Camera

2.3.2 ConfigureStream

2.3.3 Request & Result

request:

result:

一旦底层有事件上传就会走到 SyncManagerPollMethod 中:file: vendor/qcom/proprietary/camx/src/csl/hw/camxsyncmanager.cpp
--> VOID* SyncManager::SyncManagerPollMethod(VOID* pPollData)
   |--> rc = poll(fds, 2, -1)   // 监听的 syncFd 有事件上传
   |   |--> VOID* pData[] = {pEv, NULL};    // 这里的 pEv 是蕴含回调办法的,依据 setRepeatingRequest 中的剖析,这里的回调就是 Node::CSLFenceCallback
   |   |--> ioctl(pCtrl->syncFd, VIDIOC_DQEVENT, pEv);  // 取出事件
   |   |--> result = pCtrl->pThreadManager->PostJob(pCtrl->hJob, SyncManager::StoppedCbDispatchJob, pData, FALSE, FALSE);   // 这里就会调到之前注册的线程并回调 SyncManager::CbDispatchJob 办法
       file: vendor/qcom/proprietary/camx/src/csl/hw/camxsyncmanager.cpp
   |   |--> VOID* SyncManager::CbDispatchJob(VOID* pData)
   |   |   |--> Utils::Memcpy(&ev, reinterpret_cast<struct v4l2_event*> (pData), sizeof(ev)); 
   |   |   |--> pPayloadData = CAM_SYNC_GET_PAYLOAD_PTR(ev, uint64_t);
   |   |   |--> reinterpret_cast<CSLFenceHandler>(pPayloadData[0]))(reinterpret_cast<VOID* >(pPayloadData[1]), pEvHeader->sync_obj, fenceResult);   // 回调 Node::CSLFenceCallback
           file: vendor/qcom/proprietary/camx/src/core/camxnode.cpp
   |   |   |--> VOID Node::CSLFenceCallback(...)
   |   |   |   |--> result = pNode->GetThreadManager()->PostJob(pNode->GetJobFamilyHandle(), NULL, &pData[0], FALSE, FALSE) // 将工作放到 JobFamilyHandle 线程去做, 回调 Node::NodeThreadJobFamilyCb 办法
   |   |   |   |   |--> VOID* Node::NodeThreadJobFamilyCb(...)  // 因为是另一个线程解决,所以这个以缩进代表异步关系
   |   |   |   |   |   |--> FenceCallbackData* pFenceCallbackData = static_cast<FenceCallbackData*>(pCbData);  
   |   |   |   |   |   |--> NodeFenceHandlerData* pNodeFenceHandlerData = static_cast<NodeFenceHandlerData*>(pFenceCallbackData->pNodePrivateData);
   |   |   |   |   |   |--> pFenceCallbackData->pNode->ProcessFenceCallback(pNodeFenceHandlerData);
   |   |   |   |   |   |   |--> OutputPort* pOutputPort    = pFenceHandlerData->pOutputPort;
   |   |   |   |   |   |   |--> UINT64      requestId      = pFenceHandlerData->requestId;
   |   |   |   |   |   |   |--> UINT        requestIdIndex = requestId % MaxRequestQueueDepth;
   |   |   |   |   |   |   |--> m_pPipeline->NonSinkPortFenceSignaled(&pFenceHandlerData->hFence, pFenceHandlerData->requestId);    // 如果是 no sink port
                           file: vendor/qcom/proprietary/camx/src/core/camxpipeline.cpp
   |   |   |   |   |   |   |--> VOID Pipeline::NonSinkPortFenceSignaled(...)
   |   |   |   |   |   |   |   |--> m_pDeferredRequestQueue->FenceSignaledCallback(phFence, requestId);
                               file: vendor/qcom/proprietary/camx/src/core/camxdeferredrequestqueue.cpp
   |   |   |   |   |   |   |   |--> VOID DeferredRequestQueue::FenceSignaledCallback(...)
   |   |   |   |   |   |   |   |   |--> UpdateDependency(PropertyIDInvalid, phFence, NULL, requestId, 0, TRUE);
   |   |   |   |   |   |   |   |   |--> DispatchReadyNodes();
   |   |   |   |   |   |   |   |   |   |--> CamxResult result = m_pThreadManager->PostJob(m_hDeferredWorker, NULL, &pData[0], FALSE, FALSE);    // 针对所有 ready Nodes 循环解决,m_hDefferredWorker 对应的回调是 DeferredWorkerWrapper
   |   |   |   |   |   |   |   |   |   |   |--> VOID* DeferredRequestQueue::DeferredWorkerWrapper(VOID* pData)  // 异步调用, 以缩进示意
   |   |   |   |   |   |   |   |   |   |   |   |--> Dependency* pDependency = reinterpret_cast<Dependency*>(pData);
   |   |   |   |   |   |   |   |   |   |   |   |--> DeferredRequestQueue* pDeferredQueue = pDependency->pInstance;
   |   |   |   |   |   |   |   |   |   |   |   |--> result = pDeferredQueue->DeferredWorkerCore(pDependency);
   |   |   |   |   |   |   |   |   |   |   |   |   |--> pNode->ProcessRequest(&processRequest, pDependency->requestId)
                                                   file: vendor/qcom/proprietary/camx/src/core/camxnode.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |--> CamxResult Node::ProcessRequest(NodeProcessRequestData* pNodeRequestData, UINT64 requestId)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> result = ExecuteProcessRequest(&executeProcessData); // 这里临时以 ipe node 为例进行剖析
                                                       file: vendor/qcom/proprietary/camx/src/hwl/ipe/camxipenode.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> CamxResult IPENode::ExecuteProcessRequest(ExecuteProcessRequestData* pExecuteProcessRequestData)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> GetHwContext()->Submit(GetCSLSession(), m_hDevice, pIQPacket);  // 发送设置命令
                                                           file: vendor/qcom/proprietary/camx/src/core/camxhwcontext.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> CamxResult HwContext::Submit(CSLHandle hCSLSession, CSLDeviceHandle hDevice, Packet* pPacket)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> result = CSLSubmit(hCSLSession, hDevice, pPacket->GetMemHandle(), pPacket->GetOffset());
                                                               file: vendor/qcom/proprietary/camx/src/csl/camxcsl.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> CamxResult CSLSubmit(...)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> return pJumpTable->CSLSubmit(hCSL, hDevice, hPacket, offset);  // 跳转办法见 func_list_camx_chi ⑤ , 接下来我就不剖析了
   |   |   |   |   |   |   |--> m_pPipeline->SinkPortFenceSignaled(pOutputPort->sinkTargetStreamId, ...)    // 如果是 sink port
                           file: vendor/qcom/proprietary/camx/src/core/camxpipeline.cpp
   |   |   |   |   |   |   |--> VOID Pipeline::SinkPortFenceSignaled(...)
   |   |   |   |   |   |   |   |--> ResultsData resultsData = {};
   |   |   |   |   |   |   |   |--> resultsData.pPrivData = pPerRequestInfo->request.pPrivData;
   |   |   |   |   |   |   |   |--> resultsData.type      = CbType::Buffer;
   |   |   |   |   |   |   |   |--> m_pSession->NotifyResult(&resultsData);
                               file: vendor/qcom/proprietary/camx/src/core/camxsession.cpp
   |   |   |   |   |   |   |   |--> VOID Session::NotifyResult(ResultsData* pResultsData)
   |   |   |   |   |   |   |   |   |--> switch (pResultsData->type)
   |   |   |   |   |   |   |   |   |--> case CbType::Buffer:
   |   |   |   |   |   |   |   |   |--> HandleBufferCb(&pResultsData->cbPayload.buffer, pResultsData->pipelineIndex, pResultsData->pPrivData);
   |   |   |   |   |   |   |   |   |   |--> InjectResult(ResultType::BufferOK, &outBuffer, pPayload->sequenceId, pPrivData, pipelineIndex);
   |   |   |   |   |   |   |   |   |   |   |--> result = m_pThreadManager->PostJob(m_hJobFamilyHandle, NULL, &pData[0], FALSE, FALSE); // 这里的线程 cb 是 CHISession::ThreadJobCallback, 为什么呢?file: vendor/qcom/proprietary/camx/src/core/chi/camxchisession.cpp
   |   |   |   |   |   |   |   |   |   |   |--> VOID* CHISession::ThreadJobCallback(VOID* pData)
   |   |   |   |   |   |   |   |   |   |   |   |--> result = pSession->ThreadJobExecute();
   |   |   |   |   |   |   |   |   |   |   |   |   |--> result = ProcessResults();
                                                   file: vendor/qcom/proprietary/camx/src/core/camxsession.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |--> CamxResult Session::ProcessResults()
   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> LightweightDoublyLinkedListNode* pNode = m_resultHolderList.Head();
   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> bufferReady = ProcessResultBuffers(pResultHolder, metadataReady, &numResults);  // 针对每一个 node 都调用这个办法,感觉这里就是全副 node 解决 buffer 的一个过程,前期须要确认下
   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> pNode = m_resultHolderList.NextNode(pNode); // 取出下一个 node 进行操作
   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> DispatchResults(&m_pCaptureResult[0], numResults);  // 发送 results
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> m_chiCallBacks.ChiProcessCaptureResult(&pCaptureResults[index], m_pPrivateCbData);  // 这里的 m_chiCallBacks 的介绍见 func_list_camx_chi ⑦
                                                           file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxadvancedcamerausecase.h
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |-->  static VOID      ProcessResultCb(...)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> static_cast<AdvancedCameraUsecase*>(pCbData->pUsecase)->ProcessResult(pResult, pPrivateCallbackData);
                                                               file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxadvancedcamerausecase.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> VOID AdvancedCameraUsecase::ProcessResult(...)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |-->  pFeature->ProcessResult(pResult, pPrivateCallbackData);    // 如果是 AdvancedFeatureEnabled, 这里咱们思考的是预览,所以不是这分支
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> CameraUsecaseBase::SessionCbCaptureResult(pResult, pPrivateCallbackData);
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> pCameraUsecase->SessionProcessResult(pCaptureResult, pSessionPrivateData);
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> camera3_capture_result_t* pUsecaseResult     = GetCaptureResult(resultFrameIndex);
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> ChxUtils::PopulateChiToHALStreamBuffer(&pResult->pOutputBuffers[i], pResultBuffer);
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> ProcessAndReturnFinishedResults();
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> Usecase::ReturnFrameworkResult(&result, m_cameraId);
                                                                               file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxusecase.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> VOID Usecase::ReturnFrameworkResult(...)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> ExtensionModule::GetInstance()->ReturnFrameworkResult(pResult, cameraID);
                                                                                   file: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensionmodule.cpp
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> VOID ExtensionModule::ReturnFrameworkResult(const camera3_capture_result_t* pResult, UINT32 cameraID)
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |--> m_pHALOps->process_capture_result(m_logicalCameraInfo[cameraID].m_pCamera3Device, pResult); // 这里就将 result 给到下面了

2.3.4 Flush

三、Qcom Hal3 Camx 重点

上面是具体我的项目上的工作者须要晓得的 camera 相干的点, 具体细节不赘述, 这里记录下, 不便记忆.

3.1 定制化

定制 pipeline 要走那些算法及节点配置在 xml 中, 相似鱼如下门路
vendor/qcom/proprietary/chi-cdk/vendor/topology/qcom/sdm845/sdm845_usecase.xml
源码下可能因为共线有多个, 要看清楚 makefile 中指定的是哪个.

bypass 是高通做的一套框架,目标在于缩小不必要的拷贝。

3.2 性能 perflock

高通的 perflock 调试, 须要把握, 能够通过抓取 systrace 来看 cpu 相干的变动, 也能够通过读取
/sys/devices/system/cpu/ 下的信息来考察 cpu 变动状况.

3.3 常见的 node 及作用

Node 作用
BPS Bayer Processing Segment,Bayer 解决阶段。仅做 snapshot 的噪点升高和 Bayer 解决,不良像素、PDAF、LSC 校对,绿色不均衡校对,彩色级别,通道增益,demosaic,Down scaler,HDR 的合并与记录,Bayer 混合降噪等
IFE Image front-end engine,图像前端引擎。仅做 video/preview 的 Bayer 解决,做些色彩校对,Down scaler,demosaic,统计 3A 数据等
IPE Image-processing engine,图像处理引擎。由 NPS、PPS 两局部组成,次要做些硬件降噪(MFNR、MFSR)、调整大小、噪声解决、色彩解决(色差校对、色度克制)、细节加强(肤色加强)
JPEG 打包 jpeg
STATS for 3A,ISP 硬件给出的 3A 数据,用于前面的 3A 算法
IS : 图像稳固 (Image Stabilization)
RDI : 原始数据转储接口 (Raw Dump Interface)
RoI AF : 感兴趣区域 (AF Region of Interest)
SNoC 零碎: NoC (System NoC)
SOF: start of frame
ANR: application not response
MCC: mutil camera control
LPM: low power manager(低功耗下运行)
CTS/ITS: Android Camera Image Test Suite (ITS) is part of Android Compatibility Test Suite (CTS),Android 相机图像测试套件(ITS)是 Android 兼容性测试套件(CTS)的一部分验证程序,包含验证图像内容的测试。从 CTS 7.0_r8 开始,CTS Verifier 通过一体式摄像机 ITS 反对 ITS 测试自动化。持续反对手动测试,以确保涵盖所有 Android 设施尺寸。
HAF: 混合主动变焦
CRM: camera request manager
Sensor CRA(主光线角): 从镜头的传感器一侧,能够聚焦到像素上的光线的最大角度被定义为一个参数,称为主光角 (CRA)。对于主光角的一般性定义是:此角度处的像素响应升高为零度角像素响应(此时,此像素是垂直于光线的) 的 80%,https://blog.csdn.net/weixin_…,lens CRA 与 sensor 不配会使 sensor 的 pixel 呈现在光检测区域四周,使 pixel 曝光有余,亮度不够,会使整个画面造成亮度不平均的状况。还有可能造成 chroma shading 或部分色偏。部分色偏比较严重,无奈用算法弥补
Sensor HDR: sensor 在一幅图像里可能同时体现高光和暗影局部内容的能力
lens fov: 视场角, 视场角与焦距的关系:个别状况下,视场角越大,焦距就越短.
IFE: Image Front End,Bayer processing for video/preview only,HDR/De-mosic,color correction,scaler,也能够间接输入 Raw 到 RDI
RDI : Raw Dump Interface,间接从 IFE 吐出来用于 capture 的
STATS: for 3A,ISP 硬件给出的 3A 数据,用于前面的 3A 算法
PDPC: PhaseDetection Pixel Correction,相位检测像素校对
ASD: Auto scene detection,主动场景检测
CSIC: Camera serial interface decoder, 摄像机串行接口解码器
CAMIF: Ideal Raw 的第一个 dump 点
FD: Face-based, 基于人脸,也就是人脸识别
ICA: 图像校对和调整 是一个硬件单元,次要用于由镜头和静止引起的几何扭曲
LENR: 低 / 中频加强和降噪
TMC: 色调映射管制
CSID: 摄像机串行接口解码器模块
IFE: 图像前端
BPS: Bayer 解决段
IPE: 图像处理引擎
VPU: 视频处理单元
DPU: 显示处理单元
BPC: 坏像素校对
BCC: 坏群集校对
ABF: 自适应拜耳滤波器
GIC: 绿色不均衡校对
GTM: 全局色调映射
HNR: 混合降噪
ANR: 先进的降噪性能
TF: 工夫过滤器
MFNR: 多帧降噪
LTM: 部分色调映射
CS: 色度克制
ASF: 自适应空间滤波器
Upscaler: 升频器
GRA: Grain Adder(纹理减少器?)??
CPAS: 相机外围设备和反对
CAMIF: 摄像头接口???它是 VFE(video front-end)硬件的第一局部,次要工作是同步 sensor 发送数据过程中波及到的行、场同步信号。另外它还具备图像提取和图像镜像能力,CAMIF hardware 使内部 camera sensor 可能通过一些简略的内部协定链接到用户单元。为 camera 提供了数据和时钟接口,但并没有提供管制接口,最具代表行的是用 I2C 做配置和状态接口。当然,也能够是其余的一次管制信号做一些动态管制。例如:睡眠唤醒模式管制。
NPS: 噪声解决局部
PPS: 后处理局部
MCTF: 静止弥补工夫滤波 CAC、CCM、GLUT、2D LUT(二维查找表?)、CV(色彩转换)、CC(色彩校对)、SCE(肤色加强)、MCE(记忆色调加强):???
SIMO: 单输出多输入
Pedestal Correction: 基座校对
Down Scaler: 升高规模(尺寸)
Chroma Enhancement: 色度加强
Chroma Suppression: 色度克制
PDAF: 相位检测主动对焦
LSC: 镜头暗影校对
PNR: 峰值降噪
ADRC: 主动动静范畴压缩
Backlit scene: 背光场景
Garage scene: 车库场景
HNR: 升高亮度噪声,但放弃纹理细节
LDC: 镜头畸变校对
EIS: 电子稳像
Multi pass spatial noise filtering: 多通空间噪声滤波
LNR: 镜头降噪
Invert gamma: 反转伽玛
hue, saturation, lightness: 色调,饱和度,亮度
Upscaler: 升频器
ACE: 高级色度加强
CPP: 相机后处理器(相当于新版的 BPS、IPE)
BSP: board support package,板级反对安装包?也就是“做出反对安装包,来实现手机上各个硬件的基本功能”。
CCT: correlated color temperature,相干色温,具体不详;
chi-cdk: Camera Hardward Interface 相机硬件接口;Camera Development Kit,相机开发包;
HFR: High Frame Rate, min HFR=90, means>=90 时,须要 enable HFR 高帧率,目前最高 960,然而是利用插值算法计算得出的,非理论 960

3.4 日志材料

Camx 日志由属性管制, 具体也是一套规定, 首先获取权限:adb root && adb remount, 如果 remount 报错:failed: Read-only file system , 则执行adb disable-verity && adb reboot 解决,而后从新adb root && adb remount.

Camera user mode driver (UMD) ——相机用户模式驱动

UMD 的显示格局

CamX:  [<Verbosity Level>][<Group>]  <File>:<Line Number>  <Function Name> <Message>

例如:CamX : INFO camxhal3.cpp:1086 process_capture_request() frame_number 140

这里将 log 分为不同的 level,不同的 level 上面有不同的 group

如何关上指定 level 的指定 group 的 log?其各 level 和 group 见相应的 camxtypes.h

如何关上指定 level? level 间接通过 Name 设定;

group 通过二进制的每一位来确定,每个 group 对应一个 bit, 置 1 示意关上

例如:logVerboseMask=0xFFFFFFFF // 关上所有 group 的 verbose 级别的 log

         logWarningMask=0x82      //Warning 级别关上第 1 个位和第 6 位示意的 group,其实是 Sensor 和 HAL 的 group
平时测试开的 log:

如何理论进行关上 log

在手机中的:/vendor/etc/camera/camxoverridesettings.txt

例如:adb shell "echo logInfoMask=0xFFFFFFFF>> /vendor/etc/camera/camxoverridesettings.txt" 
chi log:

例如:CHX_LOG_ERROR(fmt, args);

adb shell "echo overrideLogLevels=0x1f >> /vendor/etc/camera/camxoverridesettings.txt"
或:adb shell setprop vendor.debug.camera.overrideLogLevels 0x1F (camxsettings.xml 中定义,不同的代码可能有区别)
平时开的 log:
adb shell "echo logInfoMask=0x50080 >> /vendor/etc/camera/camxoverridesettings.txt"   hal/core/chi

adb shell setprop persist.vendor.camera.logVerboseMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logEntryExitMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logInfoMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logWarningMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.logConfigMask 0xFFFFFFFF
adb shell setprop persist.vendor.camera.systemLogEnable TRUE
adb shell setprop persist.vendor.camera.logLogDRQMask 0xFFFFFFFF
camx log:
adb shell "echo overrideLogLevels=0xF >> /vendor/etc/camera/camxoverridesettings.txt" 
adb shell "echo logVerboseMask=0x1000 >> /vendor/etc/camera/camxoverridesettings.txt"
adb shell "echo logInfoMask=0xFFFFFFFF >> /vendor/etc/camera/camxoverridesettings.txt"

原文链接:https://blog.csdn.net/TaylorP…

情谊举荐:
Android 干货分享

至此,本篇已完结,如有不对的中央,欢迎您的倡议与斧正。同时期待您的关注,感谢您的浏览,谢谢!

退出移动版