Android 5.0 Camera系统源码分析(Camera预览3A流程)

万事须己运,他得非我贤。这篇文章主要讲述Android 5.0 Camera系统源码分析:Camera预览3A流程相关的知识,希望能为你提供帮助。
1. 前言 本文分析的是android Hal层的源码, 硬件平台基于mt6735。之前几篇讲的预览流程中3A相关的环节都忽略了, 现在重新整理下。
3A指的是Auto Exposure, Auto Focus, Auto White Balance。这三个一起放上来代码实在太多了, 这里将重点记录AF的代码。AF的部分工作是由ISP完成的, 而ISP的大部分代码mtk都没有开放给我们, 比如ISP是如何计算得到对焦位置信息的, 但得到对焦位置之后怎么操作对焦马达的代码我们是看得到的, 所以涉及到ISP的一些代码将被略过
2. 初始化3A 3A的初始化在DefaultCam1Device的onInit函数里面开始, 之前在camera打开流程里面已经提到过

bool DefaultCam1Device:: onInit() { ...... //(1) Open 3A mpHal3a = NS3A::IHal3A::createInstance( NS3A::IHal3A::E_Camera_1, getOpenId(), LOG_TAG); ...... }

构造一个Hal3A对象, 看下Hal3A::createInstance的实现
Hal3A* Hal3A:: createInstance(MINT32 i4SensorDevId, MINT32 i4SensorOpenIndex) { switch (i4SensorDevId) { case SENSOR_DEV_MAIN: Hal3ADev< SENSOR_DEV_MAIN> ::getInstance()-> init(i4SensorDevId, i4SensorOpenIndex); return Hal3ADev< SENSOR_DEV_MAIN> ::getInstance(); break; case SENSOR_DEV_SUB: Hal3ADev< SENSOR_DEV_SUB> ::getInstance()-> init(i4SensorDevId, i4SensorOpenIndex); return Hal3ADev< SENSOR_DEV_SUB> ::getInstance(); break; ...... } }

其实这里的Hal3A并没有直接继承IHal3A, 也就是说从IHal3A::createInstance到Hal3A::createInstance的调用过程经历了一番波折, 但暂时不用关心它。从Hal3A::createInstance可以看到除了实例化以外还会调用init函数。构造函数没什么好看的-略过, 直接看init函数
MRESULT Hal3A:: init(MINT32 i4SensorDevId, MINT32 i4SensorOpenIndex) { ...... // (1) mpStateMgr = new StateMgr(i4SensorDevId); // (2) bRet = postCommand(ECmd_Init); // (3) createThread(); // (4) bRet = IspTuningMgr::getInstance().init(m_i4SensorDev, m_i4SensorOpenIdx); // (5) ret = EnableAFThread(1); ......return S_3A_OK; }

步骤(1) new StateMgr, 构造函数如下
StateMgr::StateMgr(MINT32 sensorDevId) : ...... { #define STATE_INITIALIZE(_state_)\\ mpIState[eState_##_state_] = new State##_state_(sensorDevId, this); STATE_INITIALIZE(Init); STATE_INITIALIZE(Uninit); STATE_INITIALIZE(CameraPreview); STATE_INITIALIZE(CamcorderPreview); STATE_INITIALIZE(Recording); STATE_INITIALIZE(Precapture); STATE_INITIALIZE(Capture); STATE_INITIALIZE(AF); mpCurrentState = mpIState[eState_Uninit]; }

初始化3A的状态管理, 将各个子状态都保存在mpIState数组里面, 并将当前状态设置为Uninit状态
步骤(2) postCommand
MBOOL Hal3A::postCommand(ECmd_T const eCmd, MINTPTR const i4Arg) { ...... ERROR_CHECK(mpStateMgr-> sendCmd(eCmd)) ...... }

MRESULT StateMgr::sendCmd(ECmd_T eCmd) { Mutex::Autolock lock(m_Lock); EIntent_T eNewIntent = static_cast< EIntent_T> (eCmd); #define SEND_INTENT(_intent_)\\ case _intent_: return mpCurrentState-> sendIntent(intent2type< _intent_> ()); \\switch (eNewIntent) { SEND_INTENT(eIntent_CameraPreviewStart) SEND_INTENT(eIntent_CameraPreviewEnd) SEND_INTENT(eIntent_CaptureStart) SEND_INTENT(eIntent_CaptureEnd) SEND_INTENT(eIntent_RecordingStart) SEND_INTENT(eIntent_RecordingEnd) SEND_INTENT(eIntent_AFUpdate) SEND_INTENT(eIntent_AFStart) SEND_INTENT(eIntent_AFEnd) SEND_INTENT(eIntent_Init) SEND_INTENT(eIntent_Uninit) } return-1; }

从步骤(1)可以看出这里的mpCurrentState指向的是StateUninit对象, 所以接着看StateUninit的sendIntent函数
MRESULT StateUninit:: sendIntent(intent2type< eIntent_Init> ) { MY_LOG(" [StateUninit::sendIntent]< eIntent_Init> " ); // AAO DMA buffer init MINT32 i4SensorIdx = m_pHal3A-> getSensorOpenIdx(); if (ENABLE_3A_GENERAL & m_pHal3A-> m_3ACtrlEnable) { if (ENABLE_AAOBUF & m_pHal3A-> m_3ACtrlEnable) { // AAO DMA buffer init if (!IAAOBufMgr::getInstance().init(m_SensorDevId, i4SensorIdx)) { MY_ERR(" IAAOBufMgr::getInstance().init() fail" ); return E_3A_ERR; }if (!IAEBufMgr::getInstance().init(m_SensorDevId, i4SensorIdx)) { MY_ERR(" IAEBufMgr::getInstance().init() fail" ); return E_3A_ERR; } } if (ENABLE_AFOBUF & m_pHal3A-> m_3ACtrlEnable) { // AFO DMA buffer init if (!IAFOBufMgr::getInstance().init(m_SensorDevId, i4SensorIdx)) { MY_ERR(" IAFOBufMgr::getInstance().init() fail" ); return E_3A_ERR; } } }// State transition: eState_Uninit --> eState_Init m_pStateMgr-> transitState(eState_Uninit, eState_Init); returnS_3A_OK; }

做了一堆乱七八糟的初始化之后将3A状态从Uninit状态切换到Init状态
步骤(3) createThread和步骤(5) EnableAFThread
MVOID Hal3A::createThread() { ...... pthread_create(& mThread, NULL, onThreadLoop, this); pthread_create(& mPDThread, NULL, PDThreadLoop, this); pthread_create(& mPDVCThread, NULL, PDVCThreadLoop, this); ...... }

MRESULT Hal3A::EnableAFThread(MINT32 a_bEnable) { if (a_bEnable){ if (mbAFThreadLoop= = 0) { ...... pthread_create(& mAFThread, & attr, AFThreadFunc, this); } } else { ...... }return ret; }

一共创建了4个线程, 暂时只关心onThreadLoop 和AFThreadFunc。onThreadLoop是3A主线程, 负责接收处理命令; AFThreadFunc负责实时更新AF参数
Android 5.0 Camera系统源码分析(Camera预览3A流程)

文章图片

3. 处理PASS1_START_ISP事件 前面的3A初始化做的事情并不多, 更多的准备工作是在接收到PASS1_START_ISP事件之后做的, PASS1_START_ISP事件是在之前的Camera预览流程控制流中提到的Pass1Node的startHw函数里面发送
MBOOL Pass1NodeImpl:: startHw(list< HwPortConfig_t> & plPortCfg) { ...... handleNotify(PASS1_START_ISP, newMagicNum, 0); ...... }

3.1 DefaultCtrlNode接收处理PASS1_START_ISP事件 Pass1Node发出的event将在DefaultCtrlNode的onNotify函数中接收处理
MBOOL DefaultCtrlNodeImpl:: onNotify(MUINT32 const msg, MUINT32 const ext1, MUINT32 const ext2) { switch(msg) { case PASS1_START_ISP: { if(mpHal3a) { cmd = ECmd_CameraPreviewStart; ...... mpHal3a-> sendCommand(cmd); } case PASS1_STOP_ISP: { ...... } case PASS1_EOF: { ...... } default: { ret = MTRUE; } } return ret; }

Hal3a的sendCommand函数会把命令加入到命令队列, 然后由主线程onThreadLoop获取
MVOID* Hal3A::onThreadLoop(MVOID *arg) { while (_this-> getCommand(rCmd, bGetCmd, MFALSE)) { switch (rCmd.eCmd) { case ECmd_PrecaptureStart: { ...... } case ECmd_Update: { ...... } default: if ( ! _this-> postCommand(rCmd.eCmd, reinterpret_cast< MINTPTR> (& rCmd.rParamIspProfile))) { MY_ERR(" Cmd(%d) failed(0x%x)" , rCmd.eCmd, _this-> getErrorCode()); AEE_ASSERT_3A_HAL(" onThreadLoop postCommand fail(2)." ); } } } }

onThreadLoop通过getCommand函数获取命令, 获取到命令之后调用postCommand函数对命令进行处理
再看一次postCommand
MBOOL Hal3A::postCommand(ECmd_T const eCmd, MINTPTR const i4Arg) {if( eCmd = = ECmd_CameraPreviewStart || eCmd = = ECmd_CaptureStart) { mbEnAESenThd = MTRUE; createAEThread(); mEnFlushVSIrq = mFlushVSIrqDone = 0; mEnFlushAFIrq = mFlushAFIrqDone = 0; }...... ERROR_CHECK(mpStateMgr-> sendCmd(eCmd)) ......return MTRUE; }

接收到的命令是ECmd_CameraPreviewStart, 所以这里的createAEThread函数会执行
MVOID Hal3A::createAEThread() { pthread_create(& mAESenThread, NULL, AESensorThreadLoop, this); }

加上这个AESensorThreadLoop, 需要关注的线程增加到了3个
3.2 StateInit处理CameraPreviewStart命令 继续看mpStateMgr-> sendCmd函数。之前介绍过, 它会把命令交给当前状态的sendIntent函数进行处理。在初始化阶段已经把当前状态切换到init状态, 所以来看StateInit的sendIntent的实现
MRESULT StateInit:: sendIntent(intent2type< eIntent_CameraPreviewStart> ) {if (ENABLE_3A_GENERAL & m_pHal3A-> m_3ACtrlEnable) { if (ENABLE_AAOBUF & m_pHal3A-> m_3ACtrlEnable) { // AAO DMAInit + AAStatEnable if (!IAAOBufMgr::getInstance().DMAInit(m_SensorDevId)) { MY_ERR(" IAAOBufMgr::getInstance().DMAInit() fail" ); return E_3A_ERR; } if (!IAAOBufMgr::getInstance().AAStatEnable(m_SensorDevId, MTRUE)) { MY_ERR(" IAAOBufMgr::getInstance().AAStatEnable() fail" ); return E_3A_ERR; } if (!IAEBufMgr::getInstance().DMAInit(m_SensorDevId)) { MY_ERR(" IAEBufMgr::getInstance().DMAInit() fail" ); return E_3A_ERR; }if (!IAEBufMgr::getInstance().AAStatEnable(m_SensorDevId, MTRUE)) { MY_ERR(" IAEBufMgr::getInstance().AAStatEnable() fail" ); return E_3A_ERR; } } if (ENABLE_AFOBUF & m_pHal3A-> m_3ACtrlEnable) { // AFO DMAInit + AFStatEnable if (!IAFOBufMgr::getInstance().DMAInit(m_SensorDevId)) { MY_ERR(" IAFOBufMgr::getInstance().DMAInit() fail" ); return E_3A_ERR; } if (!IAFOBufMgr::getInstance().AFStatEnable(m_SensorDevId, MTRUE)) { MY_ERR(" IAFOBufMgr::getInstance().AFStatEnable() fail" ); return E_3A_ERR; } }......if (ENABLE_AWB & m_pHal3A-> m_3ACtrlEnable) { // AWB init bRet = (m_pHal3A-> get3APreviewMode() = = EPv_Normal) ? IAwbMgr::getInstance().cameraPreviewInit(m_SensorDevId, i4SensorIdx, rParam) : IAwbMgr::getInstance().camcorderPreviewInit(m_SensorDevId, i4SensorIdx, rParam); if (!bRet) { MY_ERR(" IAwbMgr::getInstance().PreviewInit() fail, PvMode = %d\\n" , m_pHal3A-> get3APreviewMode()); return E_3A_ERR; } }if (ENABLE_AE & m_pHal3A-> m_3ACtrlEnable) { // AE init err = (m_pHal3A-> get3APreviewMode() = = EPv_Normal) ? IAeMgr::getInstance().cameraPreviewInit(m_SensorDevId, i4SensorIdx, rParam) : IAeMgr::getInstance().camcorderPreviewInit(m_SensorDevId, i4SensorIdx, rParam); if (FAILED(err)) { MY_ERR(" IAeMgr::getInstance().PreviewInit() fail, PvMode = %d\\n" , m_pHal3A-> get3APreviewMode()); return err; } } if (ENABLE_AF & m_pHal3A-> m_3ACtrlEnable) { // AF init err = IAfMgr::getInstance().init(m_SensorDevId, i4SensorIdx); if (FAILED(err)) { MY_ERR(" AfMgr::getInstance().init() fail\\n" ); return err; } }IspTuningMgr::getInstance().sendIspTuningIOCtrl(m_SensorDevId, IspTuningMgr::E_ISPTUNING_SET_GMA_SCENARIO, IspTuningMgr::E_GMA_SCENARIO_PREVIEW, 0); IspTuningMgr::getInstance().sendIspTuningIOCtrl(m_SensorDevId, IspTuningMgr::E_ISPTUNING_NOTIFY_START, 0, 0); // Reset frame count to -2 m_pStateMgr-> resetFrameCount(); // State transition: eState_Init --> eState_CameraPreview m_pStateMgr-> transitState(eState_Init, eState_CameraPreview); returnS_3A_OK; }

包含了AWB、AE、AF在内的ISP相关的初始化, 相关的初始化完成之后会调用m_pStateMgr-> transitState函数将当前状态切换到CameraPreview状态。
代码太多, 这里只关注AF的初始化
MRESULT AfMgr::init(MINT32 i4SensorIdx, MINT32 isInitMCU) {......// --- init MCU --- SensorStaticInfo rSensorStaticInfo; if (m_i4EnableAF = = -1) { IHalSensorList* const pIHalSensorList = IHalSensorList::get(); IHalSensor* pIHalSensor = pIHalSensorList-> createSensor(" af_mgr" , m_i4SensorIdx); SensorDynamicInfo rSensorDynamicInfo; switch(m_i4CurrSensorDev) { case ESensorDev_Main: pIHalSensorList-> querySensorStaticInfo(NSCam::SENSOR_DEV_MAIN, & rSensorStaticInfo); pIHalSensor-> querySensorDynamicInfo(NSCam::SENSOR_DEV_MAIN, & rSensorDynamicInfo); break; case ESensorDev_Sub: ...... default: MY_ERR(" Invalid sensor device: %d" , m_i4CurrSensorDev); } if(pIHalSensor) pIHalSensor-> destroyInstance(" af_mgr" ); ......m_i4CurrSensorId= rSensorStaticInfo.sensorDevID; MCUDrv::lensSearch(m_i4CurrSensorDev, m_i4CurrSensorId); m_i4CurrLensId = MCUDrv::getCurrLensID(m_i4CurrSensorDev); ...... }if(isInitMCU) { m_pMcuDrv = MCUDrv::createInstance(m_i4CurrLensId); if (m_pMcuDrv-> init(m_i4CurrSensorDev) < 0) { MY_ERR(" m_pMcuDrv-> init() fail" ); m_i4EnableAF = 0; } else { m_pMcuDrv-> moveMCU( 0, m_i4CurrSensorDev); m_MoveLensTimeStamp = getTimeStamp(); } }// --- init ISP Drv/Reg --- ......// --- checking PDAF is supported or not --- ......// --- init af algo --- ......// --- NVRAM --- int err; err = NvBufUtil::getInstance().getBufAndRead(CAMERA_NVRAM_DATA_LENS, m_i4CurrSensorDev, (void*& )g_pNVRAM_LENS); if(err!= 0) MY_ERR(" AfAlgo NvBufUtil get buf fail! \\n" ); m_NVRAM_LENS.rFocusRange = g_pNVRAM_LENS-> rFocusRange; m_NVRAM_LENS.rAFNVRAM= g_pNVRAM_LENS-> rAFNVRAM; m_NVRAM_LENS.rPDNVRAM= g_pNVRAM_LENS-> rPDNVRAM; // --- Param --- m_sAFParam = getAFParam(); m_sAFConfig = getAFConfig(); m_pIAfAlgo-> setAFParam(m_sAFParam, m_sAFConfig, m_NVRAM_LENS.rAFNVRAM); m_pIAfAlgo-> initAF(m_sAFInput, m_sAFOutput); ...... m_pIAfAlgo-> setAFMode(m_eLIB3A_AFMode); //init pd mgr ......return S_AF_OK; }

第30行, 调用lensSearch函数匹配镜头驱动
第35-49行, 将镜头移动到起始位置
第60-67行, 获取af tuning参数
第69-73行, 设置af tuning参数
3.3 匹配镜头驱动 MTK为多个镜头做了兼容, 所以AF初始化的第一步就是找到当前对应镜头的型号。lensSearch函数实现了lens的匹配过程
int MCUDrv::lensSearch( unsigned int a_u4CurrSensorDev, unsigned int a_u4CurrSensorId) { INT32 i; LensCustomInit(a_u4CurrSensorDev); if (a_u4CurrSensorDev = = MCU_DEV_MAIN ) { LensCustomGetInitFunc(& MCUDrv::m_LensInitFunc_main[0]); MCUDrv::m_u4CurrLensIdx_main = 0; for (i= 0; i< MAX_NUM_OF_SUPPORT_LENS; i+ + ) { if ((MCUDrv::m_LensInitFunc_main[i].LensId = = DUMMY_LENS_ID) || (MCUDrv::m_LensInitFunc_main[i].LensId = = SENSOR_DRIVE_LENS_ID) /*|| (MCUDrv::m_LensInitFunc_main[i].LensId = = FM50AF_LENS_ID)*/ ) { MCUDrv::m_u4CurrLensIdx_main = i; } }// force assign LensIdx if SensorId != DUMMY_SENSOR_ID (to support backup lens/new lens driver) for (i= 0; i< MAX_NUM_OF_SUPPORT_LENS; i+ + ) { if ((MCUDrv::m_LensInitFunc_main[i].SensorId = = a_u4CurrSensorId) & & (a_u4CurrSensorId!= 0xFFFF) & & (a_u4CurrSensorId!= 0x0)) { MCUDrv::m_u4CurrLensIdx_main = i; MCU_DRV_DBG(" [idx]%d [CurrSensorId]0x%04x,[CurrLensIdx]0x%04x\\n" , i, a_u4CurrSensorId, MCUDrv::m_u4CurrLensIdx_main); break; } } LensCustomSetIndex(MCUDrv::m_u4CurrLensIdx_main); MCU_DRV_DBG(" [CurrLensIdx]%d" , MCUDrv::m_u4CurrLensIdx_main); } else if( a_u4CurrSensorDev = = MCU_DEV_SUB) { ...... } else return MCU_INVALID_DRIVER; return MCU_NO_ERROR; }

先看LensCustomInit函数, 由它来获取拷贝整个lens列表
MUINT32 LensCustomInit(unsigned int a_u4CurrSensorDev) { GetLensInitFuncList(& LensInitFunc[0], a_u4CurrSensorDev); return 0; }

UINT32 GetLensInitFuncList(PMSDK_LENS_INIT_FUNCTION_STRUCT pLensList, unsigned int a_u4CurrSensorDev) { if(a_u4CurrSensorDev= = 2) //sub memcpy(pLensList, & LensList_sub[0], sizeof(MSDK_LENS_INIT_FUNCTION_STRUCT)* MAX_NUM_OF_SUPPORT_LENS); else if(a_u4CurrSensorDev= = 4) //main 2 memcpy(pLensList, & LensList_main2[0], sizeof(MSDK_LENS_INIT_FUNCTION_STRUCT)* MAX_NUM_OF_SUPPORT_LENS); else// main or others memcpy(pLensList, & LensList_main[0], sizeof(MSDK_LENS_INIT_FUNCTION_STRUCT)* MAX_NUM_OF_SUPPORT_LENS); return MHAL_NO_ERROR; }

根据前后摄像头拷贝不同的LensList, 这里只看其中的LensList_main
MSDK_LENS_INIT_FUNCTION_STRUCT LensList_main[MAX_NUM_OF_SUPPORT_LENS] = { {DUMMY_SENSOR_ID, DUMMY_LENS_ID, " Dummy" , pDummy_getDefaultData}, #if defined(SENSORDRIVE) {OV3640_SENSOR_ID, SENSOR_DRIVE_LENS_ID, " kd_camera_hw" , pSensorDrive_getDefaultData}, #endif #if defined(FM50AF) {DUMMY_SENSOR_ID, FM50AF_LENS_ID, " FM50AF" , pFM50AF_getDefaultData}, #endif #if defined(DW9714AF) {IMX135_SENSOR_ID, DW9714AF_LENS_ID, " DW9714AF" , pDW9714AF_getDefaultData}, #endif ...... };

LensList_main包含了后摄所有可用的lens, 如果要新增一个lens驱动, 就需要往这个数组添加相关的信息, 看下MSDK_LENS_INIT_FUNCTION_STRUCT结构体的定义
typedef struct { UINT32 SensorId; UINT32 LensId; UINT8LensDrvName[32]; UINT32 (*getLensDefault)(VOID *pDataBuf, UINT32 size); } MSDK_LENS_INIT_FUNCTION_STRUCT, *PMSDK_LENS_INIT_FUNCTION_STRUCT;

SensorId: 表示这个lens driver配置给对应的sensor使用, 如果配置成DUMMY_SENSOR_ID则表示这个lens driver适合所有sensor使用
LensId: Lens driver的唯一标识
LensDrvName: 是实现AF功能的驱动对应的设备驱动节点名。例如FM20AF, 实现AF功能的是内核驱动里面的fm20af.c, 这个驱动会生成一个驱动节点”/dev/fm20af”
getLensDefault: 这个函数指针指向了获取AF tuning参数表的一个函数
【Android 5.0 Camera系统源码分析(Camera预览3A流程)】回到lensSearch函数, 现在lens列表已经保存在LensInitFunc数组中了, 接下来调用LensCustomGetInitFunc函数把它拷贝到m_LensInitFunc_main数组中
MUINT32 LensCustomGetInitFunc(MSDK_LENS_INIT_FUNCTION_STRUCT *a_pLensInitFunc) { if (a_pLensInitFunc != NULL) { memcpy(a_pLensInitFunc, & LensInitFunc[0], sizeof(MSDK_LENS_INIT_FUNCTION_STRUCT) * MAX_NUM_OF_SUPPORT_LENS); return 0; } return -1; }

lensSearch函数再接下来就是两个for循环, 从m_LensInitFunc_main数组中搜索符合要求的lens驱动
第一个for循环: m_u4CurrLensIdx_main指向m_LensInitFunc_main数组里lensId配置为DUMMY_LENS_ID或SENSOR_DRIVE_LENS_ID的最后一个元素
第二个for循环: 查找m_LensInitFunc_main数组中是否有SensorId和当前使用的sensor的ID相匹配的lens driver。如果有则为符合条件的第一个元素, 没有的话则为第一个for循环搜索到的结果
最后调用LensCustomSetIndex把匹配到的lens driver的index保存下来
Created with Rapha?l 2.1.0 Hal3A Hal3A StateMgr StateMgr StateInit StateInit AfMgr AfMgr MCUDrv MCUDrv camera_custom_msdk.cpp camera_custom_msdk.cpp LensList.cpp LensList.cpp postCommand sendCmd sendIntent init lensSearch LensCustomInit GetLensInitFuncList

    推荐阅读