高通camera的分辨率传递流程
创始人
2025-05-31 17:03:37
0

文章目录

  • 一、android的camera的流程图
  • 二、sensor的类型
  • 三、sensor分辨率的配置文件讲解
  • 四、sensor分辨率的配置文件如何生效
  • 五、xml的配置用法

因为最近调试关于相机的分辨率的东西,对于一个新手来说,还有很多东西要学习。
所以这篇文章记录学习高通的camera的分辨率的相关知识。
参考博客: 大佬笔记
qcom camera_sensor.xml解析
高通 chi 和 camx关系
函数说明

https://blog.csdn.net/linken_yue/article/details/124756037?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166013439016781790762652%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166013439016781790762652&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-1-124756037-null-null.142^v40^pc_rank_34,185^v2^control&utm_term=GetStaticCaps&spm=1018.2226.3001.4187

Packages->Framework->JNI->Camera(cpp)–(binder)–>CameraService->Camera HAL->Camera Driver

sensor的整体流程
先解析xml的文件配置
放到Init的data里面
然后进行probe 将init的数据写进去

一、android的camera的流程图

在这里插入图片描述

上面就是一个camera成像的一个大致原理图。
我们可以通过一张图片来看到这个RAW图(下面右边)和JPEG(下图左边)的区别(像素不太高,但是可以看出是有颜色差的)
在这里插入图片描述

二、sensor的类型

相机类型: CCD sensor 和 CMOS sensor。
CCD se当我们修改或者配置完成一个xml的时候,我们编译完成烧录到开发板里面后,
nsor (目前基本被淘汰)

  1. CCD的成像点为X-Y纵横矩阵排列,每个成像点有一个光电二极管和其控制的一个邻近电荷存储区组成。整个结构复杂,增大了耗电量,也增加了成本。简单来说,就是在同步时钟的控制下,一行行地输出信息。
  2. CCD输出的电信号还需要经过后续地址译码器、数模转化器、图像信号处理器处理,并且还需要提供三组不同电压的电源和同步时钟控制电路,集成度非常低

CMOS sensor (主流)

  1. CMOS的成像是一次性的。Sensor上所有的感光点会一次性接受光子,转换为电信号。这样一来,成像的速度大大提升
  2. CMOS光电传感器可以将所有部件集成到一块芯片上,如光敏原件、图像信号放大器、信号读取电路、数模转换器、图像信号处理器及控制器等,都可以集成到一块芯片上,还具有附加DRAM的优点。简单来说,就是CMOS的集成度更高,能够集成更多器件,适用于图像的后续处理,包括去噪、提亮等一系列算法。

现在的sensor 出图有两种,一种是YUV的sensor,一种是RAWsensor(bayer sensor),现在主流的都是RAW的sensor,因为YUV的sensor一个Pixel占2个byte,数据较大,而且只能采用内部的ISP进行处理,图像效果不太好。但是RAWsensor一个像素占8到16bit,使用平台ISP处理,能支持较大的size,所以主流的都是RAWsensor。

三、sensor分辨率的配置文件讲解

这里我们假设所有流程都没有问题,sensor可以正常点亮出图。

高通的camera sensor的初始化分辨率配置是在对应的vendor/qcom/proprietary/chi-cdk/vendor/sensor/default/目录下,这个目录下有很多不同平台的senser配置,包括索尼、豪威、三星等,对应的都是不同的xxx_sensor.xml配置文件可以自己去看目录;
xml的配置分为几个大类简介:

----------------------------------------------------------------------------------------------------------------------  	-----------------  	-------------------

还有一些配置就不说了,因为sensor这边分辨率的配置主要是修改 < slaveInfo> < initSettings> 这两个地方,这个需要向FAE寻求帮助,因为这个设计到很多寄存器,估计只有原厂才能提供帮助,因为我们自己没那么多时间去研究,自己研究起来也比较头大。
当我们修改完毕后高通可以通过对应的编译脚本将对应的xml编译为.bin文件,我们只需要将他push到对应的目录下,重启设备即可。

四、sensor分辨率的配置文件如何生效

camera的启动流程:
当android.hardware.camera.provider@2.4-service这个进程服务启动进行camera probe的时候,ImageSensorData::LoadSensorLibrary()也会进行,会把所有的编译的.bin文件都加载一遍,然后会通过sensorId进行对应的匹配

CAM_ERR : CAM-SENSOR: cam_sensor_match_id: 672 read id: 0xa201 expected id 0xa201
CAM_INFO: CAM-SENSOR: cam_sensor_driver_cmd: 1569 CAM_ACQUIRE_DEV Success, sensor_id:0xa201,sensor_slave_addr:0x20

sensor_id应该是存放在CCI总线上的寄存器下面,匹配完成后,所以内核驱动就和这个xml关联起来了
HAL层又如何关联这个xml呢:
其实xml整体就是一个 < sensorDriverData >,从xml文件的写法中也可以看出来。

他会通过一个 imagesensormodulesetmanager.cpp 文件进行解析

//文件目录
vendor/qcom/proprietary/chi-cdk/ cdk/generated/g_sensor/imagesensormodulesetmanager.cpp
//或者在out目录下
out/target/product/xxxxxxx/gen/STATIC_LIBRARIES/libcamxgenerated_intermediates/generated/g_sensor/imagesensormodulesetmanager.cpp

先介绍下这个文件:
imagesensormodulesetmanager.h 文件中创建一个类

class ImageSensorModuleSetManager : public ParameterSetManager
{
public:ImageSensorModuleSetManager();virtual ~ImageSensorModuleSetManager(){for (UINT32 i = 0; i < IMAGESENSORMODULE_DEFAULT_MODULE_COUNT; i++) //遍历所有的bin文件{PARAMETER_DELETE m_defaultModules[i];}}......//创建一个结构体指针将解析的数据存放进取CamX::SensorDriverData* GetModule_sensorDriverData(TuningMode* modeBranch,UINT32 modeCount);CamX::OISDriverData* GetModule_OISDriver(TuningMode* modeBranch,UINT32 modeCount);........
protected:virtual const ParameterModule* GetDefaultModule(char* type){const ParameterModule* module = (const ParameterModule*)m_moduleMap[type];return module;}const ParameterModule* m_defaultModules[IMAGESENSORMODULE_DEFAULT_MODULE_COUNT];std::unordered_map m_moduleMap;
};

imagesensormodulesetmanager.cpp 文件解析

ImageSensorModuleSetManager::ImageSensorModuleSetManager()
{UINT32 index = 0;m_defaultModules[index++] = (const ParameterModule*)PARAMETER_NEW CamX::EEPROMDriverDataClass("EEPROMDriverData");m_defaultModules[index++] = (const ParameterModule*)PARAMETER_NEW CamX::OISDriverDataClass("OISDriver");m_defaultModules[index++] = (const ParameterModule*)PARAMETER_NEW CamX::CameraModuleDataClass("cameraModuleData");m_defaultModules[index++] = (const ParameterModule*)PARAMETER_NEW CamX::ActuatorDriverDataClass("actuatorDriver");m_defaultModules[index++] = (const ParameterModule*)PARAMETER_NEW CamX::SensorDriverDataClass("sensorDriverData");m_defaultModules[index++] = (const ParameterModule*)PARAMETER_NEW CamX::FlashDriverDataClass("flashDriverData");m_defaultModules[index++] = (const ParameterModule*)PARAMETER_NEW CamX::PDAFConfigurationDataClass("PDConfigData");//将不同的模块分为不同的类型for (UINT32 i = 0; i < index; i++){m_moduleMap[m_defaultModules[i]->Type] = (void*)m_defaultModules[i];}
};.......................CamX::SensorDriverData* ImageSensorModuleSetManager::GetModule_sensorDriverData(TuningMode* modeBranch,UINT32 modeCount)
{//获取解析xml的配置了,至于怎么解析就不清楚了ParameterModule* pModule = GetModule((const CHAR *)"sensorDriverData",modeBranch, modeCount);//解析的数据放到对应的data里面去return (CamX::SensorDriverData*)(CamX::SensorDriverDataClass*)pModule;			
}

在这里插入图片描述

camera_sensor probe 流程

//camx/src/core/camxhwenvironment.cpp
VOID HwEnvironment::InitCaps()
{CamxResult    result = CamxResultSuccess;m_pHWEnvLock->Lock();if (InitCapsRunning == m_initCapsStatus ||InitCapsDone == m_initCapsStatus){m_pHWEnvLock->Unlock();return;}m_initCapsStatus = InitCapsRunning;if (CamxResultSuccess == result){ProbeImageSensorModules();	 //读取com.qti.sensormodule.*.binEnumerateDevices();		//CSLEnumerateDevices->CSLHwInternalProbeSensorHW,下发CAM_SENSOR_PROBE_CMD,match硬件是否成功;InitializeSensorSubModules();	//check VIDIOC_SUBSCRIBE_EVENT(V4L_EVENT_CAM_REQ_MGR_SENSOR_LOCK) CAM_HANDLE_USER_POINTER InitializeSensorStaticCaps();result = m_staticEntryMethods.GetStaticCaps(&m_platformCaps[0]);// copy the static capacity to remaining sensor'sfor (UINT index = 1; index < m_numberSensors; index++){Utils::Memcpy(&m_platformCaps[index], &m_platformCaps[0], sizeof(m_platformCaps[0]));}if (NULL != m_pOEMInterface->pInitializeExtendedPlatformStaticCaps){m_pOEMInterface->pInitializeExtendedPlatformStaticCaps(&m_platformCaps[0], m_numberSensors);}}geSensorModuleData::P
VOID HwEnvironment::ProbeImageSensorModules()
{CamxResult                      result         = CamxResultSuccess;ImageSensorModuleDataManager*   pSensorManager = NULL;result = ImageSensorModuleDataManager::Create(&pSensorManager, this); //获取驱动模块的数据ImageSensorModuleData* pData = m_pImageSensorModuleDataManager->GetImageSensorModuleData(i);    //把数据放在pData里面,后期通过操控pData进行控制result = pData->Probe(&detected, &deviceIndex); ///通过这里调用到对应的函数里面CamxResult ImageSensorModuleData::Probe

在这里插入图片描述

五、xml的配置用法

07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:481 FindBestSensorMode() Desired sensor mode:
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:482 FindBestSensorMode()     optimalWidth: 4608	//这里就是读取的最佳的分辨率
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:483 FindBestSensorMode()     optimalHeight: 3456
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:484 FindBestSensorMode()     maxWidth: 4608
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:485 FindBestSensorMode()     maxHeight: 3456
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:486 FindBestSensorMode()     minWidth: 4608
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:487 FindBestSensorMode()     minHeight: 3456
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:488 FindBestSensorMode()     frameRate: 30.000000
07-14 01:39:33.241   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:489 FindBestSensorMode()     sensorModeCaps: 00000001
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:490 FindBestSensorMode() Available sensor modes:
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:493 FindBestSensorMode()     ModeInfo[0]:
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:494 FindBestSensorMode()         modeIndex: 0
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:495 FindBestSensorMode()         arraySizeInMPix: 0
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:498 FindBestSensorMode()         frameDimension: TL:(0, 0)  width: 4640 height: 3472		//这就是我xml里面配置的分辨率
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:501 FindBestSensorMode()         cropInfo: TL:(0, 0)  width: 4639 height: 3471
07-14 01:39:33.242   686  4095 I CHIUSECASE: [INFO   ] chxfeaturezsl.cpp:822 RequestThreadProcessing() RequestThreadProcessing Entered
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:503 FindBestSensorMode()         aspectRatio: 0 / 0
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:504 FindBestSensorMode()         bpp: 10
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:505 FindBestSensorMode()         framerate: 30
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:506 FindBestSensorMode()         batchedFrames: 1
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:507 FindBestSensorMode()         caps: 00000001
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:508 FindBestSensorMode()         streamType: 00000001
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:524 FindBestSensorMode() Select sensor mode 0 condition = 0
07-14 01:39:33.242   686  3788 D CHIUSECASE: [FULL   ] chxsensorselectmode.cpp:524 FindBestSensorMode() Select sensor mode 0 condition = 2

上面log中会有一个optimal配置

ChiSensorModeInfo* ChxSensorModeSelect::FindBestSensorMode(UINT32                   cameraId,const DesiredSensorMode* pDesiredSensorMode)
{BOOL                        found               = FALSE;CDKResult                   result              = CDKResultSuccess;ChiSensorModeInfo*          pSelectedMode       = NULL;   //*******UINT32                      modeCount           = 0;ChiSensorModeInfo*          pAllModes           = NULL;SensorSelectBestResolution  selectedResolution  = {0};SensorSelectBestAspectRatio selectedAspectRatio = {10};result        = ExtensionModule::GetInstance()->GetPhysicalCameraSensorModes(cameraId, &modeCount, &pAllModes);pSelectedMode = &pAllModes[0]; // Initialize with default modeif ((CDKResultSuccess == result) &&(NULL != pDesiredSensorMode) &&(pDesiredSensorMode->forceMode >= modeCount)){CHX_LOG("Desired sensor mode:");CHX_LOG("    optimalWidth: %d", pDesiredSensorMode->optimalWidth);CHX_LOG("    optimalHeight: %d", pDesiredSensorMode->optimalHeight);CHX_LOG("    maxWidth: %d", pDesiredSensorMode->maxWidth);CHX_LOG("    maxHeight: %d", pDesiredSensorMode->maxHeight);CHX_LOG("    minWidth: %d", pDesiredSensorMode->minWidth);CHX_LOG("    minHeight: %d", pDesiredSensorMode->minHeight);CHX_LOG("    frameRate: %f", pDesiredSensorMode->frameRate);CHX_LOG("    sensorModeCaps: %08x", pDesiredSensorMode->sensorModeCaps.value);CHX_LOG("Available sensor modes:");for (UINT32 i = 0; i < modeCount; i++){CHX_LOG("    ModeInfo[%d]:", i);CHX_LOG("        modeIndex: %d", pAllModes[i].modeIndex);CHX_LOG("        arraySizeInMPix: %d", pAllModes[i].arraySizeInMPix);CHX_LOG("        frameDimension: TL:(%d, %d)  width: %d height: %d",pAllModes[i].frameDimension.left, pAllModes[i].frameDimension.top,pAllModes[i].frameDimension.width, pAllModes[i].frameDimension.height);CHX_LOG("        cropInfo: TL:(%d, %d)  width: %d height: %d",pAllModes[i].cropInfo.left, pAllModes[i].cropInfo.top,pAllModes[i].cropInfo.width, pAllModes[i].cropInfo.height);CHX_LOG("        aspectRatio: %d / %d",pAllModes[i].aspectRatio.numerator, pAllModes[i].aspectRatio.denominator);CHX_LOG("        bpp: %d", pAllModes[i].bpp);CHX_LOG("        framerate: %d", pAllModes[i].frameRate);CHX_LOG("        batchedFrames: %d", pAllModes[i].batchedFrames);CHX_LOG("        caps: %08x", pAllModes[i].sensorModeCaps.value);CHX_LOG("        streamType: %08x", pAllModes[i].streamtype);}
}

上面的最佳分辨率是通过 camx/src/hwl/titan17x/camxtitan17xcontext.cpp 这个函数进行的选择

camx/src/hwl/titan17x/camxtitan17xcontext.cppstatic const DimensionCap SupportedImageSizes[] =
{// This is the pre-defined table, and available image sizes capability// can be modified base on sensor capability{ 8000, 6000 }, // 48 MP{ 5344, 4008 }, // 21 MP{ 5312, 2988 },{ 5184, 3880 }, { 4608, 3456 }, // 16MP{ 4608, 2592 }, // 12MP{ 4160, 3120 }, // 13MP{ 4096, 2304 }, // 9.4 MP{ 4096, 2160 }, // 4k DCI{ 4000, 3000 },{ 3840, 2160 }, { 3264, 2448 }, // 8MP wide 289{ 3200, 2400 }, // 8MP  290{ 2976, 2976 }, // Square   291{ 2940, 2804 }, // cluo{ 2688, 1512 }, // 4MP  292{ 2592, 1944 }, // 5MP{ 2048, 1536 }, // 3MP{ 1554, 1634 },{ 1634, 1554 },{ 1920, 1440 }, { 1920, 1080 }, // 1080p{ 1600, 1200 }, // UXGA{ 1440, 1080 }, // Wide HD{ 1280, 960  }, // SXGA{ 1280, 768  }, // 1MP{ 1280, 720  }, // 720p{ 1080, 1080 }, // square{ 1024, 738  }, { 1024, 768  }, // XGA{ 864,  480  }, { 800,  600  }, // SVGA{ 800,  480  }, // WVGA{ 720,  1280 }, // Portrait for VT{ 720,  480  },{ 640,  480  }, { 640,  400  }, // XR 6DOF Mono{ 640,  360  },{ 352,  288  },{ 320,  240  }, { 240,  320  }, // Portrait for VT{ 176,  144  },/// @todo (CAMX-961) This list is not final, can contain more entries
};

这里面有很多分辨率,在这里,我们的sensor的xml配置是 4640 x 3472, 而在cam的sensor配置文件中并没有对应的分辨率,按照向下兼容的原则,他会默认选取一个小于sensor的分辨率,但是最接近sensor的分辨率的作为一个最佳的分辨率,最为最大值,所以他现在的分辨率为 { 4608, 3456 },这么多,他还会向下兼容,所以可以向下选取不同的分辨率。我们还可以自己添加一些合适的分辨率,但是不能自己去diy,应该有规律的,但是我目前还不知道。

后面会通过ioctl的方式将camera apk这边设定的分辨率写到对应的寄存器里面去从log中也可以看出来.

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...