相关变量介绍
frame_rate:1s时间内sensor可以出几帧 (30fps,代表sensor 1s可以吐30帧数据)
line_length_pclk:active width + blanking width (sensor的宽度与水平消隐的和)
frame_length_lines: active height + blanking height (sensor的高度与垂直消隐的和)
vt_pixel_clk:单位时间内采样pixel的数量,单位是Hz。控制像素输出的时钟,即pixel采样时钟
公式及推导
vt_pixel_clk = line_length_pclk * frame_length_lines * frame rate (我感觉把这个公式记下来就可以了,后续帧率这些都可以推导出来)
exposure_time=linecount * line_length_pclk / vt_pixel_clk
1/vt_pixel_clk :这是填充一个像素点需要的时间
line_length_pclk * 1/vt_pixel_clk : 填充一行需要的时间
linecount * line_length_pclk * 1/vt_pixel_clk : 填充linecount需要的时间就是曝光时间
这个图片可以简单的参考一下一帧数据都是由什么组成的
遇到的问题
我遇到过在专业模式下手动设置曝光时间,但是倒计时还没有到时间图片就返回了。
正常情况下底层是要hold到设定那么多时间之后在返回APP的。所以说肯定是底层的曝光参数出现了问题
(
在sensor打印log方法:
)
因为曝光的时间越久,sensor的帧率越低,到一定时间之后是需要更换sensor的setting的,所以对应的sensor mode是需要进行更换的。区分的话可以跟APP的同事进行联调,设置一些meta之类的都可以。每组setting不一样对应的支持的最大曝光时间也不一样,然后就是hal和kernel需要设置对应的timeout,不然会进入recovery模式等
最大曝光时间
这几天测cts的时候遇到一个android.hardware.camera2.cts.CaptureRequestTest#testAeModeAndLock fail的问题,这个测试项是根据HAL上报的exposurerangetime的范围分成几份来测试。然后简单追了一下最大曝光时间的来源。
路径:camx/src/core/chi/camxchicontext.cpp
CamxResult ChiContext::InitializeStaticMetadataPool(
UINT32 cameraId)
{
for (UINT key = 0; key < numCharacteristicsKeys; key++)
{
switch (pCameraInfo->pPlatformCaps->characteristicsKeys[key])
{
case SensorInfoExposureTimeRange:
{
if ((InfoSupportedHardwareLevelFull == (pCameraInfo->pPlatformCaps->supportedHwLevel)) ||
(InfoSupportedHardwareLevel3 == (pCameraInfo->pPlatformCaps->supportedHwLevel)))
{
// For FULL capability devices (android.info.supportedHardwareLevel == FULL),
// the maximum of the range SHOULD be at least 1 second (1e9), MUST be at least 100ms.
CAMX_ASSERT(pCameraInfo->pSensorCaps->maxExposureTime >= 100000000);
}
RangeINT64 timeRange;
timeRange.min = pCameraInfo->pSensorCaps->minExposureTime;
timeRange.max = pCameraInfo->pSensorCaps->maxExposureTime;
//设置meta,传递给上层
result = pStaticMetadataSlot->SetMetadataByTag(SensorInfoExposureTimeRange,
static_cast<VOID*>(&timeRange),
sizeof(RangeINT64) / sizeof(INT64),
"camxContext");
break;
}
}
}
}
路径:src/utils/camxdefs.h
const UINT64 NanoSecondsPerSecond = 1000000000ULL;
路径:camx/src/core/camximagesensordata.cpp
CamxResult ImageSensorData::GetSensorStaticCapability(
SensorModuleStaticCaps* pCapability,
UINT32 cameraID)
{
for (UINT resolutionIndex = 0; resolutionIndex < pResolutionInfo->resolutionDataCount; resolutionIndex++)
{
pCapability->maxExposureTime = ULLONG_MAX;
lineTime = Utils::RoundDOUBLE(((static_cast<DOUBLE>(GetLineLengthPixelClk(resolutionIndex,
SensorSeamlessType::None)) * NanoSecondsPerSecond) /
static_cast<DOUBLE>(GetVTPixelClk(resolutionIndex))));
maxValue = lineTime * m_pSensorData->exposureControlInfo.maxLineCount;
pCapability->maxExposureTime = Utils::MinUINT64(maxValue, pCapability->maxExposureTime);
}
}
UINT16 ImageSensorData::GetLineLengthPixelClk(
UINT resolutionIndex,
SensorSeamlessType inputSeamlessType
) const
{
UINT16 returnValue = 0;
ResolutionData* pResData = &GetResolutionInfo()->resolutionData[resolutionIndex];
if (SensorSeamlessType::None == inputSeamlessType)
{
returnValue = static_cast<UINT16>(pResData->lineLengthPixelClock);
}
else if (SensorSeamlessType::SeamlessInSensorHDR3Exp == inputSeamlessType)
{
returnValue = static_cast<UINT16>(pResData->HDR3ExposureInfo.InSensorHDR3ExpLineLengthPixelClock);
}
return returnValue;
}
UINT64 ImageSensorData::GetVTPixelClk(
UINT resolutionIndex
) const
{
ResolutionData* pResData = &GetResolutionInfo()->resolutionData[resolutionIndex];
return static_cast<UINT64>(pResData->lineLengthPixelClock * pResData->frameLengthLines * pResData->frameRate);
}
最大曝光的结果就是从上面的函数一点点计算出来的。我只把涉及到的代码给贴出来了。
从ImageSensorData::GetSensorStaticCapability这个函数中在根据sensor的xml中resolution的个数不停的计算选一个小的值。下面把对应的计算方法推导一下
pCapability->maxExposureTime = Utils::MinUINT64(maxValue, pCapability->maxExposureTime);
这步是根据当前计算的值个上一个res的参数计算出来的值选出一个最小的值当maxExposureTime
maxValue = lineTime * m_pSensorData->exposureControlInfo.maxLineCount
根据这个公式说明影响maxExposureTime有两个参数1.lineTime 2.maxLineCount 这两个参数都是正相关的,说明这两个变量的数值越大,maxExposureTime的值就会越大。maxLineCount 这个变量是可以在sensor的xml配置中找到的,说明修改这个值是可以控制maxExposureTime这个数值的大小的。
接下来就是要分析lineTime这个数值是怎么来的,我们通过控制什么可以改变maxExposureTime的数值。
lineTime =(static_cast<DOUBLE>(GetLineLengthPixelClk(resolutionIndex,SensorSeamlessType::None)) * NanoSecondsPerSecond) / static_cast<DOUBLE>(GetVTPixelClk(resolutionIndex))
这是一个除法LineLengthPixelClk VTPixelClk 这两个值的计算需要知道怎么来的
根据GetLineLengthPixelClk
LineLengthPixelClk = lineLengthPixelClock
根据GetVTPixelClk
VTPixelClk=lineLengthPixelClock*frameLengthLines*frameRate
根据上面的推到可以整合成一个公式
maxExposureTime = (lineLengthPixelClock * NanoSecondsPerSecond * maxLineCount)/
lineLengthPixelClock*frameLengthLines*frameRate
可以看出lineLengthPixelClock对曝光不会有影响,NanoSecondsPerSecond 是一个定值
所以我们可以理解为
maxExposureTime = maxLineCount / frameLengthLines*frameRate
这三个变量都是在sensor的配置中有体现,所以我们只需要在xml中对maxLineCount、frameLengthLines、frameRate 只需要改变这三个值就可以控制最大曝光时间了。