高通camera的分辨率传递流程

文章目录

  • 一、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的分辨率传递流程_第1张图片

上面就是一个camera成像的一个大致原理图。
我们可以通过一张图片来看到这个RAW图(下面右边)和JPEG(下图左边)的区别(像素不太高,但是可以看出是有颜色差的)
高通camera的分辨率传递流程_第2张图片

二、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的配置分为几个大类简介:

<sensorDriverData>
	<slaveInfo>
	  	  
	slaveInfo>
	-----------------------------------
	<regAddrInfo>
	  	  
	regAddrInfo>
	-----------------------------------
	<resolutionInfo>
	  	  
	 resolutionInfo>
	-------------------------------
	 <exposureControlInfo>
		  	  
	 exposureControlInfo>
	 -----------------
	<streamOnSettings>
		  	    	
	streamOnSettings>
	 -----------------
	<streamOffSettings>
		  	    	
	streamOffSettings>
	-------------------
	<initSettings>
			
	initSettings>
sensorDriverData>

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

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

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的分辨率传递流程_第3张图片

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

高通camera的分辨率传递流程_第4张图片

五、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 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中也可以看出来.

你可能感兴趣的:(数码相机,android)