高通usecase理解
讲得非常不错:
高通 Camera HAL3:CAMX、CHI-CDK 详解_高通camera hal3:camx、chi-cdk详解-CSDN博客
CamraHAL3数据流向图:
Camera数据从sensor出来,首先会经过IFE,然后分预览/视频和拍照2种情况。
如果是预览或者录像,是先经过IPE处理,最后输出到显示。
如果是拍照,则是先经过BSP处理,然后再经过JPEG编码器,最后保存为图片输出。
一、usecase的理解
1、usecaseid
UsecaseId:\chi-cdk\core\chiutils\chxdefs.h
/// @brief Usecase identifying enums
enum class UsecaseId
{NoMatch = 0,Default = 1,Preview = 2,PreviewZSL = 3,MFNR = 4,MFSR = 5,MultiCamera = 6,QuadCFA = 7,RawJPEG = 8,MultiCameraVR = 9,Torch = 10,YUVInBlobOut = 11,VideoLiveShot = 12,SuperSlowMotionFRC = 13,Feature2 = 14,Depth = 15,AON = 16,MaxUsecases = 17,
};
chi-cdk/oem/qcom/topology/titan/fillmore/fillmore_usecase.xml
这个 xml 文件里面描述了 82 个 usecase,但是我们的相机不一定全部跑了这些 usecase,
这些 xml 描述的只是配置,描述的 uscase 是否实现了,还要看代码里面是否实现,并使能了这些 usecase。
比如我们常接触到的有 UsecaseTorch,UsecasePreview , UsecaseVideo, UsecaseSnapshot, UsecaseZSL, UsecaseQuadCFA,UsecaseRTB,UsecaseSAT 等
选择UsecaseId
不同的UsecaseId分别对应的不同的"使用案例",
该阶段是通过调用UsecaseSelector::GetMatchingUsecase()方法来实现的,
该函数中通过传入的operation_mode、num_streams配置数据流、数量以及当前使用的Sensor个数来选择相应的UsecaseId,
比如当numPhysicalCameras值大于1,同时配置的数据流数量num_streams大于1时,选择的就是UsecaseId::MultiCamera,表示当前采用的是双摄场景。
获得usecaseid函数:chi-cdk\core\chiusecase\Chxusecaseutils.cpp
UsecaseId UsecaseSelector::GetMatchingUsecase(const LogicalCameraInfo* pCamInfo,camera3_stream_configuration_t* pStreamConfig)
{UsecaseId usecaseId = UsecaseId::Default; //第一行代码......CHX_LOG_INFO("usecase ID:%d",usecaseId);return usecaseId; //最后一行代码
}
chi-cdk\core\chiframework\Chxextensionmodule.h
UsecaseSelector* m_pUsecaseSelector; ///< Usecase selector
UsecaseFactory* m_pUsecaseFactory; ///< Usecase factory
Usecase* m_pSelectedUsecase[MaxNumImageSensors]; ///< Selected usecase
创建Usecase:
根据之前选择的UsecaseId,通过UsecaseFactory来创建相应的Usecase,
Class Usecase是所有Usecase的基类,其中定义并实现了一些通用接口,
CameraUsecaseBase继承于Usecase,并扩展了部分功能。
AdvancedCameraUsecase又继承于CameraUsecaseBase,作为主要负责大部分场景的Usecase实现类,
另外对于多摄场景,现提供了继承于AdvancedCameraUsecase的UsecaseMultiCamera来负责实现。
在这段代码中可以看到,除了双摄场景,其它大部分场景使用的都是AdvancedCameraUsecase类来创建Usecase的
创建Usecase文件以及函数:chi-cdk\core\chiframework\Chxextensionmodule.cpp
InitializeOverrideSession
CDKResult ExtensionModule::InitializeOverrideSession(uint32_t logicalCameraId,const camera3_device_t* pCamera3Device,const chi_hal_ops_t* chiHalOps,camera3_stream_configuration_t* pStreamConfig,int* pIsOverrideEnabled,VOID** pPrivate)
{...selectedUsecaseId = m_pUsecaseSelector->GetMatchingUsecase(&m_logicalCameraInfo[logicalCameraId],
pStreamConfig);...m_pSelectedUsecase[logicalCameraId] =m_pUsecaseFactory->CreateUsecaseObject(&m_logicalCameraInfo[logicalCameraId],selectedUsecaseId, m_pStreamConfig[logicalCameraId],m_multiCameraResources.hDescriptorConfig);
}
工厂模式createusecaseobject函数,是根据usecaseid创建出我们的usecase对象
函数所在文件:chi-cdk\core\chiusecase\Chxusecaseutils.cpp
函数展示如下:
Usecase* UsecaseFactory::CreateUsecaseObject(
LogicalCameraInfo* pLogicalCameraInfo, ///< camera info
UsecaseId usecaseId, ///< Usecase Id
camera3_stream_configuration_t* pStreamConfig, ///< Stream config
ChiMcxConfigHandle hDescriptorConfig) ///< mcx config
{Usecase* pUsecase = NULL;UINT camera0Id = pLogicalCameraInfo->ppDeviceInfo[0]->cameraId;switch (usecaseId){case UsecaseId::PreviewZSL:case UsecaseId::VideoLiveShot:pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);break;case UsecaseId::MultiCamera:if ((LogicalCameraType::LogicalCameraType_Default == pLogicalCameraInfo->logicalCameraType) &&(pLogicalCameraInfo->numPhysicalCameras > 1)){pUsecase = ChiMulticameraBase::Create(pLogicalCameraInfo, pStreamConfig, hDescriptorConfig);}break;case UsecaseId::MultiCameraVR://pUsecase = UsecaseMultiVRCamera::Create(pLogicalCameraInfo, pStreamConfig);break;case UsecaseId::QuadCFA:pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);break;case UsecaseId::Torch:pUsecase = UsecaseTorch::Create(pLogicalCameraInfo, pStreamConfig);break;case UsecaseId::Depth:pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);break;case UsecaseId::AON:pUsecase = CHXUsecaseAON::Create(pLogicalCameraInfo);break;default:pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);break;}return pUsecase;
}
在AdvancedCameraUsecase::Create方法中做了很多初始化操作,其中包括了以下几个阶段:
获取XML文件中Usecase配置信息
创建Feature
保存数据流,重建Usecase的配置信息
调用父类CameraUsecaseBase的initialize方法,进行一些常规初始化工作。
调用流程:
createusecaseobject -> creat ->initialize -> GetXMLUsecaseByName
总结:
usecase可以有很多的衍生类,因此会用到工厂模式来创建对象,创建对象create的过程中会回去xml的信息生成结构体到g_pipeline.h中,便于后面的使用。
UseCase在camx中很有很多衍生类,这是camx针对不同的stream来建立不同的usecase对象,用来管理选择feature,并且创建 pipeline以及session。