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的数据写进去
上面就是一个camera成像的一个大致原理图。
我们可以通过一张图片来看到这个RAW图(下面右边)和JPEG(下图左边)的区别(像素不太高,但是可以看出是有颜色差的)
相机类型: CCD sensor 和 CMOS sensor。
CCD se当我们修改或者配置完成一个xml的时候,我们编译完成烧录到开发板里面后,
nsor (目前基本被淘汰):
CMOS sensor (主流):
现在的sensor 出图有两种,一种是YUV的sensor,一种是RAWsensor(bayer sensor),现在主流的都是RAW的sensor,因为YUV的sensor一个Pixel占2个byte,数据较大,而且只能采用内部的ISP进行处理,图像效果不太好。但是RAWsensor一个像素占8到16bit,使用平台ISP处理,能支持较大的size,所以主流的都是RAWsensor。
这里我们假设所有流程都没有问题,sensor可以正常点亮出图。
高通的camera sensor的初始化分辨率配置是在对应的vendor/qcom/proprietary/chi-cdk/vendor/sensor/default/目录下,这个目录下有很多不同平台的senser配置,包括索尼、豪威、三星等,对应的都是不同的xxx_sensor.xml配置文件可以自己去看目录;
xml的配置分为几个大类简介:
<sensorDriverData>
<slaveInfo>
slaveInfo>
-----------------------------------
<regAddrInfo>
regAddrInfo>
-----------------------------------
<resolutionInfo>
resolutionInfo>
-------------------------------
<exposureControlInfo>
exposureControlInfo>
-----------------
<streamOnSettings>
streamOnSettings>
-----------------
<streamOffSettings>
streamOffSettings>
-------------------
<initSettings>
initSettings>
sensorDriverData>
还有一些配置就不说了,因为sensor这边分辨率的配置主要是修改 < slaveInfo> < initSettings> 这两个地方,这个需要向FAE寻求帮助,因为这个设计到很多寄存器,估计只有原厂才能提供帮助,因为我们自己没那么多时间去研究,自己研究起来也比较头大。
当我们修改完毕后高通可以通过对应的编译脚本将对应的xml编译为.bin文件,我们只需要将他push到对应的目录下,重启设备即可。
camera的启动流程:
当[email protected]这个进程服务启动进行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<std::string, void*> 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.*.bin
EnumerateDevices(); //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's
for (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
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 mode
if ((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.cpp
static 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中也可以看出来.