目录
UsecaseAuto create
UsecaseAuto::Initialize
1)、获取输入输出流
2)、ChiUsecase 获取usecase 的数组
3)、判断是否具有裁剪属性 打印裁剪后的分辨率
4)、解析UsecaseAuto_pipelines 的数组UsecaseAuto_AutoOfflineIFE_sink_TargetDescriptors数组配置,
5)、初始化pipeline信息
6)、初始化pipelineCreateData m_pipelineDescriptor 解析node支持的模式 配置output buffer的分辨率
6)、创建session
pipelineCreateDesc ChiPipelineCreateDescriptor 的结构体信息
Chi node info 结构体信息
1、pNodeProperties[i].pValues中保存的是支持的node 节点支持的算法信息com.qti.stats.pdlibwrapper com.qti.hvx.addconstant
2、获取HDR 模式信息 m_HDRInfo[logicalCameraId]
3、如果usecases(torch widget, AON),那么 IsNoBufferUsecase=true
4、当前场景中没使用torch widget, AON, auto usecase的 IsNoBufferUsecase = FALSE
5、获取帧率,判断是否支持HDR 模式
6、获取pLogicalCameraInfo 的m_cameraCaps.numSensorModes pSensorModeInfo
7、根据pLogicalCameraInfo判断支持那种模式的HDR
8、判断是否支持裁剪 根据设置传感器模式 设置分辨率
HDR科普
/// UsecaseAuto::Create
UsecaseAuto* UsecaseAuto::Create(
LogicalCameraInfo* pCameraInfo, ///< Camera info
camera3_stream_configuration_t* pStreamConfig) ///< Stream configuration
{
CDKResult result = CDKResultSuccess;
UsecaseAuto* pUsecaseAuto = CHX_NEW UsecaseAuto;
if (NULL != pUsecaseAuto)
{
result = pUsecaseAuto->Initialize(pCameraInfo, pStreamConfig);
if (CDKResultSuccess != result)
{
pUsecaseAuto->Destroy(FALSE);
pUsecaseAuto = NULL;
CHX_LOG_ERROR("pUsecaseAuto Initialize failed with error %s", CdkUtils::CDKResultToString(result));
}
}
else
{
result = CDKResultEFailed;
}
return pUsecaseAuto;
}
/// UsecaseAuto::Initialize
CDKResult UsecaseAuto::Initialize(
LogicalCameraInfo* pCameraInfo, ///< Camera info
camera3_stream_configuration_t* pStreamConfig) ///< Stream configuration
{
CDKResult result = CDKResultSuccess;
BOOL isMultiCamera = (pCameraInfo->numPhysicalCameras > 1);
std::map> cameraIdToStreamMap;
std::map> cameraIdToCamera3StreamMap;
m_pFrameNumCounter = 1;
m_logicalCameraId = pCameraInfo->cameraId;
m_pAppResultMutex = Mutex::Create();
m_availableResultTags = getResultVendorTags();
m_availableResultTagsOEM = ChiVendorTagUtilOEM::getResultVendorTags();
if (NULL == m_pAppResultMutex)
{
CHX_LOG_ERROR("Mutex Create failed");
result = CDKResultENoMemory;
}
if (CDKResultSuccess == result)
{
// 1. Initialize metadata Manager and initialize input client
m_pMetadataManager = ChiMetadataManager::Create(m_logicalCameraId);
if (NULL != m_pMetadataManager)
{
result = m_pMetadataManager->InitializeFrameworkInputClient(DefaultNumMetadataBuffers);
}
else
{
result = CDKResultENoMemory;
}
}
// allocate memory for the local streamconfiguration
camera3_stream_configuration_t* pStreamConfigPerPipeline = static_cast(
CHX_CALLOC(sizeof(camera3_stream_configuration_t)));
if (NULL == pStreamConfigPerPipeline)
{
result = CDKResultENoMemory;
}
// 2. Get the default matching usecase for the stream combination.
if (CDKResultSuccess == result)
{
// @todo Currently only one pipeline is returned for Auto usecase with RAW streams, handle for more?
// Create and clone the realtime pipelines for each physical camera.
for (UINT streamIdx = 0; streamIdx < pStreamConfig->num_streams; streamIdx++)
{
//获取输入输出流
camera3_stream_t* pFwkStream = pStreamConfig->streams[streamIdx];
UINT32 cameraIndex = 0;
UINT32 physicalCameraId = InvalidCameraId;
if ((NULL != pFwkStream) &&
(NULL != pFwkStream->physical_camera_id) &&
(0 < CdkUtils::StrLen(pFwkStream->physical_camera_id)))
{
physicalCameraId = static_cast(atoi(pFwkStream->physical_camera_id));
}
if (TRUE == isMultiCamera)
{
for (UINT32 index = 0; index < pCameraInfo->numPhysicalCameras; ++index)
{
if (pCameraInfo->ppDeviceInfo[index]->frameworkId == physicalCameraId)
{
cameraIndex = index;
break;
}
}
}
cameraIdToStreamMap[cameraIndex].push_back(reinterpret_cast(pFwkStream));
cameraIdToCamera3StreamMap[cameraIndex].push_back(pFwkStream);
m_StreamToCameraIdMap[reinterpret_cast(pFwkStream)] = physicalCameraId;
CHX_LOG_INFO("camera index %d stream %p camera ID %d", cameraIndex, pFwkStream, physicalCameraId);
// @todo Should return failure if logical stream is present. Add validation check.
}
m_numRTPipelines = cameraIdToStreamMap.size();
auto camera3StreamItr = cameraIdToCamera3StreamMap.begin();
for (UINT index = 0; index < m_numRTPipelines; index++)
{
std::vector pCamera3Streams = camera3StreamItr->second;
pStreamConfigPerPipeline->num_streams = pCamera3Streams.size();
pStreamConfigPerPipeline->streams = &pCamera3Streams[0];
pStreamConfigPerPipeline->session_parameters = pStreamConfig->session_parameters;
//ChiUsecase 获取usecase 的数组
m_pChiUsecase[index] = UsecaseSelector::DefaultMatchingUsecase(pStreamConfigPerPipeline, 0);
camera3StreamItr++;
}
//判断是否具有裁剪属性 打印裁剪后的分辨率
camera_metadata_entry_t entry = {};
ChxUtils::QuerySessionParam(pStreamConfig, "ScalerCropRegion", entry);
m_isScalerCropRegionEnabled = FALSE;
if (NULL != entry.data.i32)
{
CHX_LOG_INFO("m_scalerCropRegion set from session param successfully");
m_scalerCropRegion = *(reinterpret_cast(entry.data.i32));
m_isScalerCropRegionEnabled = TRUE;
}
else
{
CHX_LOG_INFO("session param not found: m_scalerCropRegion values will be 0");
}
CHX_LOG_INFO("m_scalerCropRegion {left, top, width, height} = {%d,%d,%d,%d}",
m_scalerCropRegion.left,
m_scalerCropRegion.top,
m_scalerCropRegion.width,
m_scalerCropRegion.height);
m_pChiPipelineRecRequest = static_cast(
CHX_CALLOC(sizeof(CHIPIPELINERECURRENTREQUEST) * m_numRTPipelines));
m_pChiPipelineRecSetting = static_cast(
CHX_CALLOC(sizeof(CHIPIPELINERECURRENTSETTING) * m_numRTPipelines));
// 3. Create pipeline and assign all pipeline parameters.
// Handling only realtime pipelines for Auto
auto itr = cameraIdToStreamMap.begin();//pStreamConfig->streams
for (UINT index = 0; index < m_numRTPipelines; index++)
{
UINT32 cameraIndex = itr->first;
UINT32 cameraId = pCameraInfo->ppDeviceInfo[cameraIndex]->cameraId;
UINT32 fwkCameraId = pCameraInfo->ppDeviceInfo[cameraIndex]->frameworkId;
m_cameraIdToPipelineIndexMap[fwkCameraId] = index;
std::vector pChiStreams = itr->second;
UINT32 numStreams = pChiStreams.size();
CHX_LOG_INFO("Creating Pipeline %s index:%d camera Id %d numStreams %d",
m_pChiUsecase[index]->pPipelineTargetCreateDesc[0].pPipelineName, index, cameraId, numStreams);
//UsecaseAuto_pipelines
//AutoOfflineIFE AutoYUVROI Auto AutoYUV
ChiPipelineTargetCreateDescriptor* pPipelineDesc = &m_pChiUsecase[index]->pPipelineTargetCreateDesc[0];
if (NULL != pPipelineDesc)
{
//pSinkTarget={5,UsecaseAuto_AutoOfflineIFE_sink_TargetDescriptors}
ChiTargetPortDescriptorInfo* pSinkTarget = &pPipelineDesc->sinkTarget;
ChiPortBufferDescriptor pipelineOutputBuffer[MaxChiStreams];
ChxUtils::Memset(pipelineOutputBuffer, 0, sizeof(pipelineOutputBuffer));
// Create an output buffer for every stream and its matching target
for (UINT streamIdx = 0; streamIdx < numStreams; streamIdx++)
{
for (UINT sinkIdx = 0; sinkIdx < pSinkTarget->numTargets; sinkIdx++)
{ //解析UsecaseAuto_AutoOfflineIFE_sink_TargetDescriptors数组配置
ChiTargetPortDescriptor* pSinkTargetDesc = &pSinkTarget->pTargetPortDesc[sinkIdx];
if (pSinkTargetDesc->pTarget->pChiStream == pChiStreams[streamIdx])
{
//pStream = UsecaseAuto_TARGET_BUFFER_RAW2_target
pipelineOutputBuffer[streamIdx].pStream = pSinkTargetDesc->pTarget->pChiStream;
//pNodePort=s_69_TARGET_BUFFER_RAW2_Link_NodeDescriptors
pipelineOutputBuffer[streamIdx].pNodePort = pSinkTargetDesc->pNodePort;
//numNodePorts=1
pipelineOutputBuffer[streamIdx].numNodePorts = pSinkTargetDesc->numNodePorts;
CHX_LOG_INFO("Creating output buffer for stream: %p, idx: %d, format: %d and matching target idx: %d",
pChiStreams[streamIdx], streamIdx, pChiStreams[streamIdx]->format, sinkIdx);
}
}
}
m_pPipelines[index] = Pipeline::Create(cameraId, PipelineType::Default);
if (NULL != m_pPipelines[index])
{
//初始化pipeline信息
m_pPipelines[index]->SetOutputBuf
//配置node信息 UsecaseAuto_pipelines[0]的pipelineCreateDesc信息
// pipelineCreateDesc={ 0, 3, UsecaseAuto_AutoOfflineIFENodes, 7, UsecaseAuto_AutoOfflineIFELinks, 1, 0, { 0 }, { 0 }}
m_pPipelines[index]->SetPipelineNodePorts(&pPipelineDesc->pipelineCreateDesc);
m_pPipelines[index]->SetPipelineName(pPipelineDesc->pPipelineName);
m_pPipelines[index]->SetPipelineLogicalCameraId(m_logicalCameraId);
m_pPipelines[index]->SetPipelineContext(ChiMultiContextType::DefaultContext);
m_privData[index].streamIndex = index;
m_physFwkCameraIds[index] = std::to_string(fwkCameraId);
m_requiredResultVendorTag.tagIds.insert(
end(m_requiredResultVendorTag.tagIds), begin(m_availableResultTagsOEM), end(m_availableResultTagsOEM));
m_requiredResultVendorTag.tagIds.insert(
end(m_requiredResultVendorTag.tagIds), begin(m_availableResultTags), end(m_availableResultTags));
ChiMetadata* pMetadata = m_pPipelines[index]->GetDescriptorMetadata();
result = pMetadata->SetTag("com.qti.chi.availableResults",
"RequiredResultVendorTags",
&m_requiredResultVendorTag,
sizeof(RequiredResultVendorTags));
if (CDKResultSuccess != result)
{
CHX_LOG_WARN("SetTag failed to setavailableResults");
result = CDKResultSuccess;
}
//初始化pipelineCreateData m_pipelineDescriptor
//解析node支持的模式 配置output buffer的分辨率
result = m_pPipelines[index]->CreateDescriptor();
}
else
{
result = CDKResultEFailed;
CHX_LOG_ERROR("Pipeline creation failed for pipeline with index: %d", index);
}
if (CDKResultSuccess != result)
{
CHX_LOG_ERROR("CreateDescriptor of pipeline %s failed with error %s",
pPipelineDesc->pPipelineName, CdkUtils::CDKResultToString(result));
}
itr++;
}
}
// 4. Create session
if (CDKResultSuccess == result)
{
auto itr = cameraIdToStreamMap.begin();
for (UINT index = 0; index < m_numRTPipelines; index++)
{
UINT32 cameraIndex = itr->first;
UINT32 fwkCameraId = pCameraInfo->ppDeviceInfo[cameraIndex]->frameworkId;
UINT32 pipelineIndex = m_cameraIdToPipelineIndexMap[fwkCameraId];
UINT32 numPipelines = DefaultNumAutoPipeline;
ChiCallBacks callbacks = { 0 };
callbacks.ChiNotify = SessionCbNotifyMessage;
callbacks.ChiProcessCaptureResult = SessionCbCaptureResult;
callbacks.ChiProcessRecurrentCaptureResult = SessionCbRecurrentCaptureResult;
m_RTSessionPvtData.sessionId = index;
m_RTSessionPvtData.pUsecase = this;
//创建session
m_pRTSession[index] = Session::Create(&m_pPipelines[index], numPipelines, &callbacks, &m_RTSessionPvtData);
if (NULL == m_pRTSession[index])
{
result = CDKResultEFailed;
CHX_LOG_ERROR("Session creation failed");
}
m_pipelineIdxToSessionMap[pipelineIndex] = m_pRTSession[index];
CHX_LOG_VERBOSE("Mapping Pipeline idx %d to stream %p", pipelineIndex, m_pRTSession[index]);
itr++;
}
}
}
if (CDKResultSuccess == result)
{
result = AllocateRecurrentRequest();
}
// 5. Register metadata clients.
if (CDKResultSuccess == result)
{
for (UINT index = 0; index < m_numRTPipelines; index++)
{
Pipeline* pPipeline = m_pPipelines[index];
m_metadataClients[index] =
m_pMetadataManager->RegisterClient(
pPipeline->IsRealTime(),
pPipeline->GetTagList(),
pPipeline->GetTagCount(),
pPipeline->GetPartialTagCount(),
pPipeline->GetMetadataBufferCount() + BufferQueueDepth,
ChiMetadataUsage::RealtimeOutput);
CHX_LOG_ERROR("Register Client Id: %d", m_metadataClients[index]);
pPipeline->SetMetadataClientId(m_metadataClients[index]);
}
}
// get extension module instance for pipeline activation
ExtensionModule * pExtensionModuleInstance = ExtensionModule::GetInstance();
if (NULL == pExtensionModuleInstance)
{
result = CDKResultEFailed;
CHX_LOG_ERROR("Extension module is NULL");
}
// 6. Activate the pipelines.
// @todo Add resource manager checks before activating
if (CDKResultSuccess == result)
{
for (UINT index = 0; index < m_numRTPipelines; index++)
{
CHX_LOG_CORE_CFG("ActivatePipeline %s", m_pPipelines[index]->GetPipelineName());
result = pExtensionModuleInstance->ActivatePipeline(m_pRTSession[index]->GetSessionHandle(),
m_pRTSession[index]->GetPipelineHandle(0));
if (CDKResultSuccess == result)
{
m_pPipelines[index]->SetPipelineActivateFlag();
}
else
{
CHX_LOG_ERROR("Activate %s failed! result: %s", m_pPipelines[index]->GetPipelineName(),
CdkUtils::CDKResultToString(result));
break;
}
}
// If any of activate failed, then deactivate all the pipelines and report error.
if (CDKResultSuccess != result)
{
for (UINT index = 0; index < m_numRTPipelines; index++)
{
Pipeline* pPipeline = m_pPipelines[index];
if (TRUE == pPipeline->IsPipelineActive())
{
CHX_LOG_CORE_CFG("DeActivatePipeline %s", pPipeline->GetPipelineName());
result = pExtensionModuleInstance->DeactivatePipeline(m_pRTSession[index]->GetSessionHandle(),
m_pRTSession[index]->GetPipelineHandle(index),
CHIDeactivateModeDefault);
if (CDKResultSuccess == result)
{
pPipeline->SetPipelineDeactivate();
}
else
{
CHX_LOG_ERROR("Deactivate %s failed! result: %s", pPipeline->GetPipelineName(),
CdkUtils::CDKResultToString(result));
}
}
}
}
}
// release local stream configuration
if (NULL != pStreamConfigPerPipeline)
{
CHX_FREE(pStreamConfigPerPipeline);
}
return result;
}
/// @brief Structure that contains all information required to create a pipeline
1127typedef struct ChiPipelineCreateDescriptor
1128{
1129 UINT32 size; ///< Size of this structure
1130 UINT32 numNodes; ///< Number of pipeline nodes
1131 CHINODE* pNodes; ///< Pipeline nodes
1132 UINT32 numLinks; ///< Number of links
1133 CHINODELINK* pLinks; ///< Each link descriptor
1134 UINT32 isRealTime; ///< Is this a realtime pipeline
1135 UINT numPipelineModes; ///< Number of pipeline modes (transition modes)
1136 UINT pipelineModeIds[MaxNumberOfModes]; ///< Array of transition mode ids
1137 const CHAR* pipelineModeNames[MaxNumberOfModes]; ///< Array of transition mode names
1138 UINT numBatchedFrames; ///< Number of framework frames batched
1139 UINT maxFPSValue; ///< maxFPSValue info of batched frames
1140 UINT32 cameraId; ///< Camera Id of pipeline
1141 CHIMETAHANDLE hPipelineMetadata; ///< Valid Metadata buffer handle containing tags init tags
1142 BOOL HALOutputBufferCombined; ///< Is the HAL output buffer combined for batch mode
1143 UINT32 logicalCameraId;
///< Logical Camera Id of pipeline
1144} CHIPIPELINECREATEDESCRIPTOR;
pipelineCreateDesc=
{
0,
3,
UsecaseAuto_AutoOfflineIFENodes,
7,
UsecaseAuto_AutoOfflineIFELinks,
1,
0,
{ 0 },
{ 0 }
}
/// @brief Chi node info
1086typedef struct ChiNode
1087{
1088 CHINODEPROPERTY* pNodeProperties; ///< Properties associated with the node
1089 UINT32 nodeId; ///< Node identifier
1090 UINT32 nodeInstanceId; ///< Node instance identifier
1091 CHINODEPORTS nodeAllPorts; ///< Information about all ports
1092 UINT32 numProperties; ///< Count of NodeProperty instances in pNodeProperties
1093 PruneSettings pruneProperties; ///< A list of prune properties
1094 UINT32 preferredMode; ///< Preferred mode to be used for sensor initialization
1095 UINT32 numTransitionModes; ///< Number of transition modes
1096 UINT32 transitionModeIds[MaxNumberOfModes]; ///< Transition mode Ids
1097} CHINODE;
static ChiNodeProperty UsecaseAuto_AutoOfflineIFE_node0_0_properties[] =
{
{1, "com.qti.stats.pdlibwrapper"},
};
static ChiNodeProperty UsecaseAuto_AutoOfflineIFE_node65536_1_properties[] =
{
{2, "1"},
{37, "0"},
};
static ChiNodeProperty UsecaseAuto_AutoOfflineIFE_node65636_0_properties[] =
{
{1, "com.qti.hvx.addconstant"},
{6, "1"},
};
static ChiNode UsecaseAuto_AutoOfflineIFENodes[] =
{
{UsecaseAuto_AutoOfflineIFE_node0_0_properties, 0, 0, {0, { 0 }, NULL, 1, { 0 }, UsecaseAuto_AutoOfflineIFENode0_0OutputPortDescriptors}, 1, {0, NULL}, 0, 0, { 0 }},
{UsecaseAuto_AutoOfflineIFE_node65536_1_properties, 65536, 1, {1, { 0 }, UsecaseAuto_AutoOfflineIFENode65536_1InputPortDescriptors, 2, { 0 }, UsecaseAuto_AutoOfflineIFENode65536_1OutputPortDescriptors}, 2, {0, NULL}, 0, 0, { 0 }},
{UsecaseAuto_AutoOfflineIFE_node65636_0_properties, 65636, 0, {1, { 0 }, UsecaseAuto_AutoOfflineIFENode65636_0InputPortDescriptors, 4, { 0 }, UsecaseAuto_AutoOfflineIFENode65636_0OutputPortDescriptors}, 2, {0, NULL}, 0, 0, { 0 }},
};
typedef UINT32 NodeProperty;
static const NodeProperty NodePropertyCustomLib = 1; ///< Custom lib
static const NodeProperty NodePropertyProfileId = 2; ///< IPE/BPS Instance Property Profile
static const NodeProperty NodePropertyStabilizationType = 3; ///< IPE Instance Property Stabilization Type
static const NodeProperty NodePropertyProcessingType = 4; ///< IPE Instance Property Processing Type
static const NodeProperty NodePropertyIPEDownscale = 5; ///< IPE Instance IPE downscale
139static const NodeProperty NodePropertyStatsSkipPattern = 6;
static const NodeProperty NodePropertyIFECSIDHeight = 7;
static const NodeProperty NodePropertyIFECSIDWidth = 8;
static const NodeProperty NodePropertyIFECSIDLeft = 9;
static const NodeProperty NodePropertyIFECSIDTop = 10;
static const NodeProperty NodePropertyNodeClass = 11; ///< Node class -
解析ChiNode 中的node info 信息
modeCount:
pLogicalCameraInfo->m_cameraCaps.numSensorModes
pAllModes:
pLogicalCameraInfo->pSensorModeInfo
1)、采用三曝光实现实时HDR预览
2)、Staggered HDR 行交织 HD
3)、MFHDR 多帧 HDR
4)、QHDR(Quad HDR,四像素HDR)
// Pipeline::CreateDescriptor
CDKResult Pipeline::CreateDescriptor()
{
CDKResult result = CDKResultSuccess;
PipelineCreateData pipelineCreateData = {};
m_pipelineDescriptor.isRealTime = HasSensorNode(&m_pipelineDescriptor);
// m_cameraId from usecase side must be correct, even for pipelines without sensor Node
m_pipelineDescriptor.cameraId = m_cameraId;
m_pipelineDescriptor.logicalCameraId = m_logicalCameraId;
m_pipelineDescriptor.context = m_context;
pipelineCreateData.pPipelineName = m_pPipelineName;
pipelineCreateData.numOutputs = m_numOutputBuffers;
pipelineCreateData.pOutputDescriptors = &m_pipelineOutputBuffer[0];
pipelineCreateData.numInputs = m_numInputBuffers;
pipelineCreateData.pInputOptions = &m_pipelineInputOptions[0];
pipelineCreateData.pPipelineCreateDescriptor = &m_pipelineDescriptor;
CHIPIPELINECREATEDESCRIPTOR* pCreateDesc = pipelineCreateData.pPipelineCreateDescriptor;
pCreateDesc->numBatchedFrames = ExtensionModule::GetInstance()->GetNumBatchedFrames(m_logicalCameraId);
pCreateDesc->HALOutputBufferCombined = ExtensionModule::GetInstance()->GetHALOutputBufferCombined();
pCreateDesc->maxFPSValue = ExtensionModule::GetInstance()->GetUsecaseMaxFPS(m_logicalCameraId);
const CHAR* pClientName = "Chi::Pipeline::CreateDescriptor";
SetTuningUsecase();
m_pPipelineDescriptorMetadata->AddReference(pClientName);
m_pipelineDescriptor.hPipelineMetadata = m_pPipelineDescriptorMetadata->GetHandle();
CHX_LOG_CORE_CFG("Pipeline[%s] pipeline pointer %p numInputs=%d, numOutputs=%d stream w x h: %d x %d "
"format: %d, numBatchedFrames: %d, HALOutputBufferCombined: %d maxFPSValue: %d cameraId: %d logicalCameraId:%d",
m_pPipelineName,
this,
pipelineCreateData.numInputs,
pipelineCreateData.numOutputs,
(NULL != pipelineCreateData.pOutputDescriptors->pStream) ? pipelineCreateData.pOutputDescriptors->pStream->width : 0,
(NULL != pipelineCreateData.pOutputDescriptors->pStream) ? pipelineCreateData.pOutputDescriptors->pStream->height : 0,
(NULL != pipelineCreateData.pOutputDescriptors->pStream) ? pipelineCreateData.pOutputDescriptors->pStream->format : 0,
pCreateDesc->numBatchedFrames,
pCreateDesc->HALOutputBufferCombined,
pCreateDesc->maxFPSValue,
pipelineCreateData.pPipelineCreateDescriptor->cameraId,
pipelineCreateData.pPipelineCreateDescriptor->logicalCameraId);
UINT32 enableSWMCTFwithReferenceFrame = ExtensionModule::GetInstance()->GetMCTFwithReferenceFrameStatus(m_logicalCameraId);
ChxUtils::SetVendorTagValue(m_pPipelineDescriptorMetadata,
VendorTag::SWMCTFEnableWithRef,
1,
&enableSWMCTFwithReferenceFrame);
UINT32 facialContourVersion = ExtensionModule::GetInstance()->GetFacialContourVersion(m_logicalCameraId);
ChxUtils::SetVendorTagValue(m_pPipelineDescriptorMetadata,
VendorTag::FacialContourVersion,
1,
&facialContourVersion);
// Update stats skip pattern in node property with value from override
//m_pipelineDescriptor.numNodes=3
for (UINT node = 0; node < m_pipelineDescriptor.numNodes; node++)
{
//pNodes[node]=UsecaseAuto_AutoOfflineIFENodes[node]
const ChiNode* const pChiNode = &m_pipelineDescriptor.pNodes[node];
//pChiNode->numProperties=1 2 4
//pChiNode->pNodeProperties=UsecaseAuto_AutoOfflineIFE_node0_0_properties
// UsecaseAuto_AutoOfflineIFE_node65536_1_properties
// UsecaseAuto_AutoOfflineIFE_node65536_0_properties
for (UINT i = 0; i < pChiNode->numProperties; i++)
{
//pChiNode->pNodeProperties[i].id=1
switch(pChiNode->pNodeProperties[i].id)
{ //解析node的算法
//pNodeProperties[i].pValues = com.qti.stats.pdlibwrapper com.qti.hvx.addconstant
case NodePropertyStatsSkipPattern://6
m_statsSkipPattern = ExtensionModule::GetInstance()->GetStatsSkipPattern();
pChiNode->pNodeProperties[i].pValue = &m_statsSkipPattern;
break;
case NodePropertyEnableFOVC://16
m_enableFOVC = ExtensionModule::GetInstance()->EnableFOVCUseCase();
pChiNode->pNodeProperties[i].pValue = &m_enableFOVC;
break;
case NodePropertyNISInternalTrigger://21
m_isNISInternalTrigger = ExtensionModule::GetInstance()->IsInternalTriggered(m_logicalCameraId);
pChiNode->pNodeProperties[i].pValue = &m_isNISInternalTrigger;
break;
default:
break;
}
}
}
//初始化pCreatePipelineDescriptor m_hPipelineHandle
m_hPipelineHandle = ExtensionModule::GetInstance()->CreatePipelineDescriptor(&pipelineCreateData);
m_pPipelineDescriptorMetadata->ReleaseReference(pClientName);
if (NULL == m_hPipelineHandle)
{
result = CDKResultEFailed;
CHX_LOG_ERROR("Fail due to NULL pipeline handle");
}
else
{//获取HDR 模式信息 m_HDRInfo[logicalCameraId]
const HDRInfo& rHDRInfo = ExtensionModule::GetInstance()->GetHDRInfo(m_logicalCameraId);
HDRDeviceInfo* pLogicalHDRDeviceInfo = rHDRInfo.pLogicalHDRDeviceInfo;
ChiHDRModeInfo physicalHDRModeInfo =
ExtensionModule::GetInstance()->GetPhysicalDeviceHDRModeInfo(m_logicalCameraId, m_cameraId);
ChiHDRFeatureMode physicalHDRMode = physicalHDRModeInfo.HDRMode;
//usecases(torch widget, AON). IsNoBufferUsecase=true
//auto usecase IsNoBufferUsecase = FALSE
if ((FALSE == ExtensionModule::GetInstance()->IsNoBufferUsecase()))
{
// sensor mode selection not required for no buffer usecases(torch widget, AON).
DesiredSensorMode desiredSensorMode = {};
//获取帧率
desiredSensorMode.frameRate = ExtensionModule::GetInstance()->GetUsecaseMaxFPS(m_logicalCameraId);
//判断是否支持HDR 模式
if (ExtensionModule::GetInstance()->IsVideoHDRMode())
{
const auto sensorModes = [&]() -> ChiPtrView
{
UINT32 modeCount = 0;
CHISENSORMODEINFO* pAllModes = NULL;
//获取pLogicalCameraInfo modeCount pAllModes
//pLogicalCameraInfo->m_cameraCaps.numSensorModes
//pLogicalCameraInfo->pSensorModeInfo;
if (CDKResultSuccess == ExtensionModule::GetInstance()->GetPhysicalCameraSensorModes(m_cameraId,
&modeCount,
&pAllModes))
{
return ChiPtrView{static_cast(modeCount), pAllModes};
}
return ChiPtrView(static_cast(0), NULL);
}();
auto SupportsZZHDR = [&](const ChiSensorModeInfo& rSensorModeInfo)
{
return rSensorModeInfo.sensorModeCaps.u.ZZHDR;
};
desiredSensorMode.sensorModeCaps.u.ZZHDR = std::any_of(sensorModes.begin(), sensorModes.end(), SupportsZZHDR);
}//采用三曝光实现实时HDR预览
else if (SelectInSensorHDR3ExpUsecase::InSensorHDR3ExpPreview ==
ExtensionModule::GetInstance()->SelectInSensorHDR3ExpUsecase())
{
desiredSensorMode.sensorModeCaps.u.IHDR = 1;
}//Staggered HDR 行交织 HDR
else if (HDRFeatureModeSHDR == physicalHDRMode)
{
desiredSensorMode.sensorModeCaps.u.SHDR = 1;
desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::TwoExposure;
if (FALSE == rHDRInfo.isAutoHDREnabled)
{
switch (rHDRInfo.appReqNumHDRExposure)
{
case SingleHDRExposure:
desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::OneExposure;
break;
case TwoHDRExposure:
desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::TwoExposure;
break;
case ThreeHDRExposure:
desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::ThreeExposure;
break;
default:
desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::TwoExposure;
break;
}
}
}//MFHDR 多帧 HDR
else if (HDRFeatureModeMFHDR == physicalHDRMode)
{
desiredSensorMode.sensorModeCaps.u.Normal = TRUE;
// For MFHDR case, we will run sensor @ twice the desired output framerate
desiredSensorMode.frameRate *= 2;
}//QHDR(Quad HDR,四像素HDR)
else if (HDRFeatureModeQHDR == physicalHDRMode)
{
if (TRUE == rHDRInfo.appEnabledQHDR)
{
desiredSensorMode.sensorModeCaps.u.QHDR = 1;
desiredSensorMode.sensorHDRExposureType = ChiHDRExposureType::ThreeExposure;
}
}
UINT index = FindHighestWidthInputIndex(m_pipelineInputOptions, m_numInputOptions);
// @todo Select the highest width/height from all the input buffer requirements
desiredSensorMode.optimalWidth = m_pipelineInputOptions[index].bufferOptions.optimalDimension.width;
desiredSensorMode.optimalHeight = m_pipelineInputOptions[index].bufferOptions.optimalDimension.height;
desiredSensorMode.maxWidth = m_pipelineInputOptions[index].bufferOptions.maxDimension.width;
desiredSensorMode.maxHeight = m_pipelineInputOptions[index].bufferOptions.maxDimension.height;
desiredSensorMode.minWidth = m_pipelineInputOptions[index].bufferOptions.minDimension.width;
desiredSensorMode.minHeight = m_pipelineInputOptions[index].bufferOptions.minDimension.height;
desiredSensorMode.forceMode = ExtensionModule::GetInstance()->GetForceSensorMode(m_cameraId);
if (TRUE == m_isSensorModeHintSet)
{
CHX_LOG("input option:%dx%d, upscale:%d, override optimal size:%dx%d, sensor mode caps:%x",
desiredSensorMode.optimalWidth, desiredSensorMode.optimalHeight,
m_SensorModePickhint.postSensorUpscale,
m_SensorModePickhint.sensorOutputSize.width,
m_SensorModePickhint.sensorOutputSize.height,
m_SensorModePickhint.sensorModeCaps.value);
//判断是否支持裁剪 根据设置传感器模式 设置分辨率
if ((TRUE == m_SensorModePickhint.postSensorUpscale) &&
(m_SensorModePickhint.sensorOutputSize.width < desiredSensorMode.optimalWidth) &&
(m_SensorModePickhint.sensorOutputSize.height < desiredSensorMode.optimalHeight))
{
desiredSensorMode.optimalWidth = m_SensorModePickhint.sensorOutputSize.width;
desiredSensorMode.optimalHeight = m_SensorModePickhint.sensorOutputSize.height;
desiredSensorMode.maxWidth = desiredSensorMode.optimalWidth;
desiredSensorMode.maxHeight = desiredSensorMode.optimalHeight;
desiredSensorMode.minWidth = desiredSensorMode.optimalWidth;
desiredSensorMode.minHeight = desiredSensorMode.optimalHeight;
}
if (0 != m_SensorModePickhint.sensorModeCaps.value)
{
desiredSensorMode.sensorModeCaps.value = m_SensorModePickhint.sensorModeCaps.value;
}
if (0 != m_SensorModePickhint.frameRateMultiplier)
{
desiredSensorMode.frameRate *= m_SensorModePickhint.frameRateMultiplier;
}
if (TRUE == m_SensorModePickhint.sensorModeCaps.u.QuadCFA)
{
desiredSensorMode.sensorRemosaicType = ExtensionModule::GetInstance()->GetRemosaicType();
}
}
if (StreamConfigModeFastShutter == ExtensionModule::GetInstance()->GetOpMode(m_cameraId))
{
desiredSensorMode.sensorModeCaps.u.FS = 1;
}
if (HDRFeatureModeQHDR == physicalHDRMode)
{
// QCFA binning mode
if (FALSE == rHDRInfo.appEnabledQHDR)
{
desiredSensorMode.optimalWidth = m_pipelineInputOptions[index].bufferOptions.optimalDimension.width >> 1;
desiredSensorMode.optimalHeight = m_pipelineInputOptions[index].bufferOptions.optimalDimension.height >> 1;
}
}
m_pSelectedSensorMode = ChxSensorModeSelect::FindBestSensorMode(m_cameraId, &desiredSensorMode);
m_pSelectedSensorMode->batchedFrames = ExtensionModule::GetInstance()->GetNumBatchedFrames(m_logicalCameraId);
m_pSelectedSensorMode->HALOutputBufferCombined = ExtensionModule::GetInstance()->GetHALOutputBufferCombined();
}
if (TRUE == m_pipelineDescriptor.isRealTime)
{
if ((NULL != pLogicalHDRDeviceInfo) &&
(HDRFeatureModeSHDR == pLogicalHDRDeviceInfo->HDRModeInfo.HDRMode) &&
(InvalidMode != ExtensionModule::GetInstance()->GetForceSensorMode(m_cameraId)))
{
// This is to handle the case wherre overridesensor mode is used
pLogicalHDRDeviceInfo->numHDRExposure = static_cast(m_pSelectedSensorMode->HDRExposureType) + 1;
}
m_pipelineInfo.pipelineInputInfo.isInputSensor = TRUE;
m_pipelineInfo.pipelineInputInfo.sensorInfo.cameraId = m_cameraId;
m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo = m_pSelectedSensorMode;
CHX_LOG_CORE_CFG("Pipeline[%s] Pipeline pointer %p Selected sensor Mode W=%d, H=%d Mode=%d",
m_pPipelineName,
this,
m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo->frameDimension.width,
m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo->frameDimension.height,
m_pipelineInfo.pipelineInputInfo.sensorInfo.pSensorModeInfo->modeIndex);
std::vector transition_modes = {1, 2, 3};
std::copy(transition_modes.begin(), transition_modes.end(), std::back_inserter(m_transitionModesList));
// add changes to get the list of seamless mode transitions possible for this sensor mode
}
else
{
m_pipelineInfo.pipelineInputInfo.isInputSensor = FALSE;
m_pipelineInfo.pipelineInputInfo.inputBufferInfo.numInputBuffers = m_numInputBuffers;
m_pipelineInfo.pipelineInputInfo.inputBufferInfo.pInputBufferDescriptors = GetInputBufferDescriptors();
if ((FALSE == ExtensionModule::GetInstance()->IsNoBufferUsecase()))
{
CHIBUFFERDIMENSION sensorOutDim = {};
sensorOutDim.width = m_pSelectedSensorMode->frameDimension.width;
sensorOutDim.height = m_pSelectedSensorMode->frameDimension.height;
for (UINT32 i = 0; i < m_numInputOptions; i++)
{
CHIBUFFEROPTIONS& rBufferOptions = m_pipelineInputOptions[i].bufferOptions;
if ((rBufferOptions.minDimension.width > sensorOutDim.width) ||
(rBufferOptions.minDimension.height > sensorOutDim.height))
{
CHX_LOG_INFO("override min requirement to sensor output size. %dx%d -> %dx%d",
rBufferOptions.minDimension.width, rBufferOptions.minDimension.height,
sensorOutDim.width, sensorOutDim.height);
rBufferOptions.minDimension = sensorOutDim;
}
if ((rBufferOptions.minDimension.width > rBufferOptions.optimalDimension.width) ||
(rBufferOptions.minDimension.height > rBufferOptions.optimalDimension.height))
{
rBufferOptions.optimalDimension = rBufferOptions.minDimension;
}
}
}
}
m_pipelineInfo.hPipelineDescriptor = reinterpret_cast(m_hPipelineHandle);
m_pipelineInfo.pipelineOutputInfo.hPipelineHandle = NULL;
m_pipelineInfo.pipelineResourcePolicy = m_resourcePolicy;
m_pipelineInfo.isDeferFinalizeNeeded = m_isDeferFinalizeNeeded;
}
return result;
}
https://deepinout.com/hdr/img-sensor-hdr-mode-intro.html
https://sspai.com/post/62228#!
https://deepinout.com/hdr/understand-the-various-types-of-hdr.html