前言
每次在追CSL这块代码的的时候找着找着就被一堆函数指针指来指去,就把我给指晕了。好好的一个函数名被改过来改过去的。然后后面就是跟着自己的感觉来追的。
于是决定好好的找下这个jumptable到底是怎么回事。下面的这些都是我又是正向反向各种推找理出来的。然后按照顺序整理了一下。
流程讲解
在camx中有个camxsettings.xml文件里面有着各种各样的配置,什么dump图,log开关这些property都写在里面的。其中有个属性是CSLMode就是会决定我们最后jumptable会用到哪个类型的。
路径:camx/src/settings/common/camxsettings.xml
<setting>
<Name>CSL Mode</Name>
<Help>Selects run-time CSL mode</Help>
<VariableName>CSLMode</VariableName>
<VariableType>CSLModeType</VariableType>
<SetpropKey>vendor.debug.camera.CSLMode</SetpropKey>
<DefaultValue>Hardware</DefaultValue>
<Dynamic>FALSE</Dynamic>
</setting>
其中上面的这个属性会被解析保存到struct StaticSettings这个结构中,后面感兴趣的话可以分析一下。会把这个值存放到params这个参数中。provider起来的时候会调用HwEnvironment初始化的函数,这个CSLMode会被传入到CSLInitializ函数。
路径:camx/src/core/camxhwenvironment.cpp
CamxResult HwEnvironment::Initialize()
{
const StaticSettings* pStaticSettings = pStaticSettingsManager->GetStaticSettings();
params.mode = pStaticSettings->CSLMode;
result = CSLInitialize(¶ms);
}
CSLInitialize这里要注意函数名一样的有两个地方,一个是带参数的一个是没有带参数的。带参数的是没有范围限制的,没有带参数的是CSLJumpTable的成员是有范围的我们这里调用的时候带参数的,后面会调用到没有参数的CSLInitialize。这里的几个函数都很重要。
1.创建CSLModeManager
2.获取到刚刚创建的Jumptable实例
3.调用对用创建的JumpTable实例的初始化方法
路径:camx/src/csl/camxcsl.cpp
CamxResult CSLInitialize(
CSLInitializeParams* pInitializeParams)
{
g_pCSLModeManager = CAMX_NEW CSLModeManager(pInitializeParams);
CSLJumpTable* pJumpTable = g_pCSLModeManager->GetJumpTable();
return pJumpTable->CSLInitialize();
}
1.创建CSLModeManager
创建对应的 CSLModeManager里面主要就是通过我们之前获取到的CSLMode的数值来创建对应的Jumptanble实例。这个case里面的条件的表示方法好像跟之前的不太一样。其实数值是一样的就是枚举换了一个名字而已,可以参考一下对应的代码。
路径:camx/src/csl/camxcsljumptable.cpp
CSLModeManager::CSLModeManager(
const CSLInitializeParams* pInitParams)
{
m_emulatedSensorParams = pInitParams->emulatedSensorParams;
switch (pInitParams->mode)
{
case CSLMode::CSLHwEnabled:
m_pJumpTable = GetCSLJumpTableHw();
m_mode = static_cast<CSLMode>(pInitParams->mode);
break;
case CSLMode::CSLIFHEnabled:
m_pJumpTable = GetCSLJumpTableIFH();
m_mode = static_cast<CSLMode>(pInitParams->mode);
break;
}
}
路径: camx/src/csl/camxcsl.h
typedef enum
{
CSLHwEnabled, ///< HW Enabled
CSLIFHEnabled, ///< IFH Enabled
CSLPresilEnabled, ///< Presil CSIM Enabled
CSLPresilRUMIEnabled, ///< Presil RUMI Enabled
} CSLMode;
路径: camx/src/settings/g_camxsettings.h
enum CSLModeType
{
CSLModeHardware, ///< Hardware CSL implementation, using the standard CamX KMD and hardware
CSLModeIFH, ///< Infinitely Fast Hardware CSL implementation, bypassing the KMD
CSLModePresil, ///< Presil CSIM CSL Implementation
CSLModePresilRUMI, ///< Presil RUMI CSL Implementation
};
这里就是根据对应的mode去获取到对应类型的jumptable实例
路径:camx/src/csl/hw/camxcslhw.cpp
CSLJumpTable* GetCSLJumpTableHw()
{
return &g_CSLjumpTableHW;
}
路径:camx/src/csl/ifh/camxcslifh.cpp
CSLJumpTable* GetCSLJumpTableIFH(void)
{
return &g_CSLjumpTableIFH;
}
这个是JumpTable的结构体定义和Hareware这个类型的结构体变量的定义,如果是其他类型的JumpTable也是一样的。
可以看出来JumpTable中定义的成员都是函数指针,所以定义这个结构体成员是需要对里面的指针进行定义的。然后不同类型的JumpTable调用这些指针就可以调用的对应不同类型定制的函数中。
路径:camx/src/csl/camxcsljumptable.h
struct CSLJumpTable
{
CamxResult (*CSLInitialize)(void);
CamxResult (*CSLUninitialize)(void);
CamxResult (*CSLOpen)(
CSLHandle* phCSL);
CamxResult (*CSLClose)(
CSLHandle hCSL);
CamxResult (*CSLAddReference)(
CSLHandle hCSL);
CamxResult (*CSLQueryCameraPlatform)(
CSLCameraPlatform* pCameraPlatform);
CamxResult (*CSLImageSensorProbe)(
CSLMemHandle hPacket,
SIZE_T offset,
CSLImageSensorProbeResult* pProbeResult);
CamxResult (*CSLSetDebugBuffer)(
CSLHandle hCSL,
CSLDebugBufferType type,
CSLMemHandle hBuffer,
SIZE_T offset,
SIZE_T length,
CSLDebugBufferResult* pDebugBufferResult);
CamxResult (*CSLEnumerateDevices)(
CSLDeviceDescriptor* pDeviceDescriptor);
CamxResult (*CSLQueryDeviceCapabilities)(
INT32 deviceIndex,
VOID* pDeviceData,
SIZE_T deviceDataSize);
CamxResult (*CSLAcquireDevice)(
CSLHandle hCSL,
CSLDeviceHandle* phDevice,
INT32 deviceIndex,
CSLDeviceResource* pDeviceResourceRequest,
SIZE_T numDeviceResources,
CSLDeviceAttribute* pDeviceAttribute,
SIZE_T numDeviceAttributes,
const CHAR* pDeviceName);
CamxResult (*CSLReleaseDevice)(
CSLHandle hCSL,
CSLDeviceHandle hDevice);
CamxResult (*CSLLink)(
CSLHandle hCSL,
CSLDeviceHandle* phDevices,
UINT handleCount,
CSLLinkHandle* phLink);
CamxResult (*CSLUnlink)(
CSLHandle hCSL,
CSLLinkHandle* phLink);
CamxResult (*CSLSyncLinks)(
CSLHandle hCSL,
CSLLinkHandle* phLink,
UINT handleCount,
CSLLinkHandle hMasterhLink,
CSLSyncLinkMode syncMode);
CamxResult (*CSLOpenRequest)(
CSLHandle hCSL,
CSLLinkHandle hLink,
UINT64 requestId,
BOOL bubble,
CSLSyncLinkMode syncMode,
UINT32 expectedExposureTimeInMs);
CamxResult (*CSLCancelRequest)(
CSLHandle hCSL,
const CSLFlushInfo& pCSLFlushInfo);
CamxResult (*CSLStreamOn)(
CSLHandle hCSL,
CSLLinkHandle* phLink,
CSLDeviceHandle* phDevices);
CamxResult (*CSLStreamOff)(
CSLHandle hCSL,
CSLLinkHandle* phLink,
CSLDeviceHandle* phDevices,
CSLDeactivateMode mode);
CamxResult(*CSLSingleDeviceStreamOn)(
CSLHandle hCSL,
INT32 deviceIndex,
CSLDeviceHandle* phDevice);
CamxResult(*CSLSingleDeviceStreamOff)(
CSLHandle hCSL,
INT32 deviceIndex,
CSLDeviceHandle* phDevice);
CamxResult (*CSLSubmit)(
CSLHandle hCSL,
CSLDeviceHandle hDevice,
CSLMemHandle hPacket,
SIZE_T offset);
CamxResult(*CSLFlushLock)(
CSLHandle hCSL,
const CSLFlushInfo& rCSLFlushInfo);
CamxResult(*CSLFlushUnlock)(
CSLHandle hCSL);
CamxResult (*CSLRegisterMessageHandler)(
CSLHandle hCSL,
CSLLinkHandle hCSLLinkHandle,
CSLMessageHandler handler,
VOID* pUserData);
CamxResult (*CSLRegisterSessionMessageHandler)(
CSLHandle hCSL,
CSLSessionMessageHandler msgHandler,
VOID* pUserData);
CamxResult (*CSLAlloc)(
const CHAR* pStr,
CSLBufferInfo* pBufferInfo,
SIZE_T bufferSize,
SIZE_T alignment,
UINT32 flags,
const INT32* pDeviceIndices,
UINT deviceCount);
CamxResult (*CSLMapBuffer)(
CSLBufferInfo* pBufferInfo,
INT bufferFD,
SIZE_T offset,
SIZE_T bufferLength,
UINT32 flags,
const INT32* pDeviceIndices,
UINT deviceCount);
CamxResult (*CSLMapNativeBuffer)(
CSLBufferInfo* pBufferInfo,
const CSLNativeHandle* phNativeBuffer,
SIZE_T offset,
SIZE_T bufferLength,
UINT32 flags,
const INT32* pDeviceIndices,
UINT deviceCount);
CamxResult (*CSLGetBufferInfo)(
CSLMemHandle hBuffer,
CSLBufferInfo* pBufferInfo);
CamxResult (*CSLBufferCacheOp)(
CSLMemHandle hBuffer,
BOOL invalidate,
BOOL clean);
CamxResult (*CSLReleaseBuffer)(
CSLMemHandle hBuffer);
CamxResult (*CSLReleaseBufferForced)(
CSLMemHandle hBuffer);
CamxResult (*CSLCreatePrivateFence)(
const CHAR* pName,
CSLFence* pFenceOut);
CamxResult (*CSLCreateNativeFence)(
CSLNativeFenceCreateDataPtr pCreateData,
CSLFence* pFenceOut);
CamxResult (*CSLMergeFences)(
CSLFence* phFences,
SIZE_T fenceCount,
CSLFence* pFenceOut);
CamxResult (*CSLGetFenceAttrib)(
CSLFence hFence,
UINT32 attrib,
VOID* pAttribVal,
UINT32 valSize);
CamxResult (*CSLFenceWait)(
CSLFence hFence,
UINT64 timeout);
CamxResult (*CSLFenceWaitMultiple)(
CSLFence* phFences,
BOOL* pFenceSignaled,
SIZE_T fenceCount,
UINT64 timeout);
CamxResult (*CSLFenceAsyncWait)(
CSLFence hFence,
CSLFenceHandler handler,
VOID* pUserData);
CamxResult (*CSLFenceAsyncCancel)(
CSLFence hFence,
CSLFenceHandler handler,
VOID* pUserData);
CamxResult (*CSLFenceSignal)(
CSLFence hFence,
CSLFenceResult status);
CamxResult (*CSLReleaseFence)(
CSLFence hFence);
CamxResult(*CSLAcquireHardware)(
CSLHandle hCSL,
CSLDeviceHandle hDevice,
CSLDeviceResource* pDeviceResourceRequest,
UINT32 version);
CamxResult(*CSLReleaseHardware)(
CSLHandle hCSL,
CSLDeviceHandle hDevice);
CamxResult (*CSLDumpRequest) (
CSLHandle hCSL,
CSLDumpRequestInfo* pDumpRequestInfo,
SIZE_T* pFilledLength);
};
这是Hareware的Mode对应的Jumptable,可以类比看出这个结构体变量中成员是跟上面一一对应的。所以说我们调用上面的那些函数指针的时候要确定我们的CSLMode,这样就可以快速找到我们用的是哪个类型的JumpTable了。
路径:camx/src/csl/hw/camxcslhw.cpp
CSLJumpTable g_CSLjumpTableHW =
{
CSLInitializeHW,
CSLUninitializeHW,
CSLOpenHW,
CSLCloseHW,
CSLAddReferenceHW,
CSLQueryCameraPlatformHW,
CSLImageSensorProbeHW,
CSLSetDebugBufferHW,
CSLEnumerateDevicesHW,
CSLQueryDeviceCapabilitiesHW,
CSLAcquireDeviceHW,
CSLReleaseDeviceHW,
CSLLinkHW,
CSLUnlinkHW,
CSLSyncLinksHW,
CSLOpenRequestHW,
CSLCancelRequestHW,
CSLStreamOnHW,
CSLStreamOffHW,
CSLSingleDeviceStreamOnHW,
CSLSingleDeviceStreamOffHW,
CSLSubmitHW,
CSLFlushLockHW,
CSLFlushUnlockHW,
CSLRegisterMessageHandlerHW,
CSLRegisterSessionMessageHandlerHW,
CSLAllocHW,
CSLMapBufferHW,
CSLMapNativeBufferHW,
CSLGetBufferInfoHW,
CSLBufferCacheOpHW,
CSLReleaseBufferHW,
CSLReleaseBufferForcedHW,
CSLCreatePrivateFenceHW,
CSLCreateNativeFenceHW,
CSLMergeFencesHW,
CSLGetFenceAttribHW,
CSLFenceWaitHW,
CSLFenceWaitMultipleHW,
CSLFenceAsyncWaitHW,
CSLFenceAsyncCancelHW,
CSLFenceSignalHW,
CSLReleaseFenceHW,
CSLAcquireHardwareHW,
CSLReleaseHardwareHW,
CSLDumpRequestHW
};
2.获取创建类型的Jumptable实例
这里要跟之前获取各个类型的jumptable区分。上面各个类型的时已经定义好的变量,这里是获取上面的jumpdable的一个保存,并且是CSLModeManager的一个成员变量。
路径:camx/src/csl/camxcsljumptable.h
inline CSLJumpTable* GetJumpTable() const
{
return m_pJumpTable;
}
3.调用JumpTable实例的初始化方法
因为我们这个平台的CSLMode是Hardware所以我这里只举例了Hw相关的,看着这个初始化主要就是获取KMD的device还有SyncManager是跟request同步相关的,这个还是挺重要的后面研究一下展开说说。
路径:camx/src/csl/hw/camxcslhw.cpp
CamxResult CSLInitializeHW()
{
CSLHwEnumerateAndAddCSLHwDevice(CSLInternalHwVideodevice, CAM_VNODE_DEVICE_TYPE);
CSLHwEnumerateAndAddCSLHwDevice(CSLInternalHwVideoSubdevice, CAM_CPAS_DEVICE_TYPE);
g_CSLHwInstance.pSyncFW = CamX::SyncManager::GetInstance();
g_CSLHwInstance.pSyncFW->Initialize(syncDeviceName);
CSLHwInstanceSetState(CSLHwValidState);
}
这是我整理画出来的简单的函数流程图,感觉看起来还是比较清晰的,比那种只上代码的感觉要舒服很多,然后可以简单推断出对应的代码结构和函数调用结构这些。如果还有类图做搭配的话应该会更加清晰一些。等后面有时间在补充一下。看不清楚的可以放大看下。