(1)概念
- MTK打闪一般分为预闪、主闪两个阶段。相应的执行一次拍照会有预闪、主闪两次开灯。预闪可以用来防红眼(red-eye reduction)。闪光时使环境发生变化,会按新的光线条件(有闪光时)重新测光,来实现更精确;
- 预闪是开灯让AE/AF收敛,其持续的时间取决于AF/AF收敛的速度,Flash本身没有控制预闪时间长短的能力。理论上环境亮度越暗,对应的Sensor Framerate越低,AE/AF收敛的时间就越长(AE收敛完之后,才会做AF收敛)。预闪阶段会提前计算主闪时会使用的参数(AE/AWB/AF/Duty)。
- 主闪是在Capture阶段去开灯,一般flow至少会亮三张Frame,在第三帧P1 Done关灯。主闪Duty, doCap要使用的AE参数、AWB权重、AF lock focus都是在预闪阶段就决定了。所以主闪的持续时间相对比预闪的会短一些,电流强度也会稍微高一点。
这里我们以普通的mt6761为例,可以查看部分代码的设置。
(2)闪光灯Hal逻辑代码
//vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/flash_mgr/flash_hal.cppint FlashHal::getTorchStatus()
{logI("getTorchStatus(): torch status(%d).", mTorchStatus);return mTorchStatus;
}int FlashHal::setTorchOnOff(MBOOL enable)
{logI("[CAT][flash] setTorchOnOff(): type:%d enable:%d", mStrobeTypeId, enable);if (mStrobeTypeId == STROBE_TYPE_FRONT && !cust_isSubFlashSupport())return 1;if (enable == 1) {init();setInCharge(1);setOnOff(enable, FLASH_HAL_SCENARIO_TORCH);mTorchStatus = 1;} else {setOnOff(enable, FLASH_HAL_SCENARIO_TORCH);setInCharge(0);uninit();mTorchStatus = 0;}return 0;
}int FlashHal::setVideoTorchOnOff(int enable)
{logI("setVideoTorchOnOff(): enable(%d).", enable);setOnOff(enable, FLASH_HAL_SCENARIO_VIDEO_TORCH);return 0;
}int FlashHal::setAfLampOnOff(int enable)
{logI("setAfLampOnOff(): enable(%d).", enable);setOnOff(enable, FLASH_HAL_SCENARIO_AF_LAMP);return 0;
}int FlashHal::setPfOnOff(int enable)
{logI("setPfOnOff(): enable(%d).", enable);setOnOff(enable, FLASH_HAL_SCENARIO_PRE_FLASH);return 0;
}int FlashHal::setCaptureFlashOnOff(int enable)
{logI("setCaptureFlashOnOff(): enable(%d).", enable);setOnOff(enable, FLASH_HAL_SCENARIO_MAIN_FLASH);return 0;
}int FlashHal::setTorchDuty(int level)
{int duty = 0, dutyLt = 0;logI("setTorchLevel(): level(%d).", level);mTorchLevel = level;FlashCustomAdapter::getInstance(mSensorDev)->getTorchDuty(level, &duty, &dutyLt);mpStrobe->setDuty(duty);if (mStrobeCtNum > 1) {mpStrobe2->setDuty(dutyLt);}return 0;
}//setOnOff
int FlashHal::setOnOff(int enable, FLASH_HAL_SCENARIO_ENUM scenario)
{logI("[CAT][flash] setOnOff(): type:%d enable:%d scenario:%d", mStrobeTypeId, enable, scenario);/* verify arguments */if (verifyScenario(scenario)) {logE("setOnOff(): invalid arguments.");return -1;}if (!isAvailable()) {logI("setOnOff(): sensorDev(%d) not available.", mSensorDev);return -1;}if (scenario == FLASH_HAL_SCENARIO_MAIN_FLASH) {//...} else if (scenario == FLASH_HAL_SCENARIO_VIDEO_TORCH) {//...}if (enable)return setFlashOn(mFlashHalInfo[scenario]);elsereturn setFlashOff();
}
(3)关闭真闪配置
//vendor/mediatek/proprietary/custom/mt6761/hal/camera_3a/flashawb_tuning_custom.cppMBOOL
isFlashAWBv2Enabled(MINT32 i4SensorDev)
{switch (i4SensorDev){case NSIspTuning::ESensorDev_Main: // Main Sensorreturn MTRUE;//MFALSEcase NSIspTuning::ESensorDev_MainSecond: // Main Second Sensorreturn MTRUE;case NSIspTuning::ESensorDev_Sub: // Sub Sensorreturn MTRUE;case NSIspTuning::ESensorDev_SubSecond: // Sub Second Sensorreturn MTRUE;default:return MTRUE;}
}
(4)默认关闭双闪通道,并进行闪光灯校准
//kernel-4.19/arch/arm64/boot/dts/mediatek/mt6761.dtsflashlight_core: flashlight_core {compatible = "mediatek,flashlight_core";};flashlights_mt6370: flashlights_mt6370 {compatible = "mediatek,flashlights_mt6370";decouple = <1>;//默认为0,需要配置为1channel@1 {type = <0>;ct = <0>;part = <0>;};};flashlights_aw3644: flashlights_aw3644 {compatible = "mediatek,flashlights_aw3644";};
//vendor/mediatek/proprietary/custom/mt6761/hal/flashlight/flash_custom.cppint cust_isDualFlashSupport(int sensorDev)
{if(sensorDev == DUAL_CAMERA_MAIN_SENSOR || sensorDev == DUAL_CAMERA_MAIN_2_SENSOR)return 0;elsereturn 0;return 0;
}
如下修改为闪光灯校准:vendor/mediatek/proprietary/custom/mt6761/hal/flashlight/flash_tuning_custom_cct.cpp
(5)闪光灯亮度相关参数
//vendor/mediatek/proprietary/custom/mt6761/hal/flashlight//flash_tuning_custom_cct.cpp
//--------------------//eng level//index mode//torchp->engLevel.torchDuty = 6;//手电筒亮度//afp->engLevel.afDuty = 6;//对焦闪光灯亮度//pf, mf, normalp->engLevel.pfDuty = 6;//预闪亮度p->engLevel.mfDutyMax = 27;//主闪亮度范围值p->engLevel.mfDutyMin = 0;//...
(6)闪光灯打闪Log分析
(A)main Log查看(3次打闪)
打闪几次可通过如下Log判断。
W TaskMgr : [sendEvent] TaskEvent:TouchAEStart, fgLampflashCond(1)/bCustEnableFlash(1)/bStrobeBVTrigger(1)
W TaskMgr : [sendEvent] TaskEvent:TouchAEStart, fgLampflashCond(1)/bCustEnableFlash(1)/bStrobeBVTrigger(1)
W TaskMgr : [sendEvent] TaskEvent:TouchAEStart, fgLampflashCond(1)/bCustEnableFlash(1)/bStrobeBVTrigger(1)
另可通过如下源码查看调用过程。
//vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/isp_30/ae_mgr/ae_mgr.cppMBOOL AeMgr::IsStrobeBVTrigger()
{MBOOL bStrobeBVTrigger;MINT32 i4Bv = 0;if (m_rAEInitInput.rAEPARAM.strAEParasetting.bEV0TriggerStrobe == MTRUE){// The strobe trigger by the EV 0 indexi4Bv = m_BVvalueWOStrobe;}else{if (m_rAEInitInput.rAEPARAM.pEVValueArray[m_eAEEVcomp]){if (m_pIAeAlgo != NULL){i4Bv = m_BVvalueWOStrobe + m_pIAeAlgo->getSenstivityDeltaIndex(1024 * 1024 / m_rAEInitInput.rAEPARAM.pEVValueArray[m_eAEEVcomp]);}else{i4Bv = m_BVvalueWOStrobe;AE_LOG("[%s()] The AE algo class is NULL, i4SensorDev:%d line:%d\n", __FUNCTION__, m_eSensorDev, __LINE__);}}}bStrobeBVTrigger = (i4Bv < m_CurrentCaptureTable.i4StrobeTrigerBV)?MTRUE:MFALSE;AE_LOG_IF(m_3ALogEnable, "[%s()] i4SensorDev:%d bStrobeBVTrigger:%d BV:%d %d\n", __FUNCTION__, m_eSensorDev, bStrobeBVTrigger, i4Bv, m_CurrentCaptureTable.i4StrobeTrigerBV);return bStrobeBVTrigger;
}
可通过如上Code中的bStrobeBVTrigger字段来查看当前环境值和打闪阈值。
D ae_mgr : [IsStrobeBVTrigger()] i4SensorDev:1 bStrobeBVTrigger:0 BV:11 -28
D ae_mgr : [IsStrobeBVTrigger()] i4SensorDev:1 bStrobeBVTrigger:0 BV:10 -28
D ae_mgr : [IsStrobeBVTrigger()] i4SensorDev:1 bStrobeBVTrigger:1 BV:-36 -28
D ae_mgr : [IsStrobeBVTrigger()] i4SensorDev:1 bStrobeBVTrigger:0 BV:-2 -28
备注:具体打闪阈值通过效果文件来控制。
//camera_AE_PLineTable_xxxxraw.hstatic constexpr strAETable g_AE_PreviewAutoTable =
{AETABLE_RPEVIEW_AUTO, //eAETableID147, //u4TotalIndex-28, //i4StrobeTrigerBV //为当前配置的打闪阈值102, //i4MaxBV-44, //i4MinBV, Original:-4590, //i4EffectiveMaxBV-30, //i4EffectiveMinBVLIB3A_AE_ISO_SPEED_AUTO, //ISOsPreviewPLineTable_60Hz,sPreviewPLineTable_50Hz,NULL,
};
(B)kernel Log查看(3次打闪)
//预闪
kernel_log_6__2023_0613_212218:10220: <7>[ 2188.129555] (0)[7550:3AEventThd]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 1
kernel_log_6__2023_0613_212218:11035: <7>[ 2189.912077] (2)[7550:3AEventThd]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0
//主闪
kernel_log_6__2023_0613_212218:11260: <7>[ 2190.348990] (0)[7467:3ATHREAD]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 1
kernel_log_6__2023_0613_212218:11305: <7>[ 2190.453573] (3)[7512:CAM_P1]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0
kernel_log_6__2023_0613_212218:11463: <7>[ 2190.665271] (1)[7467:3ATHREAD]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0kernel_log_6__2023_0613_212218:12779: <7>[ 2193.272978] (1)[7639:3AEventThd]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 1
kernel_log_6__2023_0613_212218:13307: <7>[ 2194.481592] (3)[7639:3AEventThd]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0
kernel_log_6__2023_0613_212218:13497: <7>[ 2194.918873] (0)[7467:3ATHREAD]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 1
kernel_log_6__2023_0613_212218:13542: <7>[ 2195.016548] (1)[7512:CAM_P1]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0
kernel_log_6__2023_0613_212218:13705: <7>[ 2195.222145] (2)[7467:3ATHREAD]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0kernel_log_6__2023_0613_212218:15349: <7>[ 2198.889098] (2)[7653:3AEventThd]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 1
kernel_log_6__2023_0613_212218:15942: <7>[ 2200.201315] (3)[7653:3AEventThd]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0
kernel_log_6__2023_0613_212218:16129: <7>[ 2200.869104] (3)[7467:3ATHREAD]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 1
kernel_log_6__2023_0613_212218:16174: <7>[ 2200.967390] (0)[7512:CAM_P1]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0
kernel_log_6__2023_0613_212218:16347: <7>[ 2201.322911] (1)[7467:3ATHREAD]flashlight: _flashlight_ioctl: FLASH_IOC_SET_ONOFF(0,0,0): 0